简体   繁体   English

为什么我的对象是指针?

[英]Why is my object a pointer?

My question concerns the use of objects in C#. 我的问题涉及C#中对象的使用。 I think I understand what's happening, but I want to understand why. 我想我了解发生了什么,但我想了解原因。 For reasons I won't go into, I want to create a temporary copy of an object with its current data (current state). 由于我不愿讨论的原因,我想使用其当前数据(当前状态)创建对象的临时副本。 So I thought I could create a new object, assign it the original object, then change the original object. 所以我想我可以创建一个新对象,为其分配原始对象,然后更改原始对象。 At that point I would have two objects in different states. 到那时,我将有两个处于不同状态的对象。 But what happens is that the copied object ends up looking exactly like the first. 但是发生的是,复制的对象最终看起来与第一个对象完全一样。 Here is some code to illustrate: 这是一些代码说明:

Order o1 = new Order();
o1.property1 = "test 1";

Order o2 = new Order();
o2 = o1;

o1.property1 = "test 2";

But at the end of this code, both o1 and o2 have property1 set to "test 2". 但是在此代码的结尾,o1和o2都将property1设置为“ test 2”。 I think I realize that all objects are just pointers, so if you change one it changes another, but I can't understand why this is, or why it is useful. 我想我意识到所有对象都只是指针,所以如果您更改一个对象,它也会更改另一个对象,但是我不明白为什么这样,或者为什么有用。 Is there some fundamental thing I'm missing here? 我在这里缺少一些基本的东西吗? Also, what would be the best way to accomplish what I want to do? 另外,完成我想做的最好的方法是什么? Which is: store the state of the object, make changes, then revert if necessary. 即:存储对象的状态,进行更改,然后在必要时还原。 Hopefully this makes sense. 希望这是有道理的。

An object variable in C# is a reference (not a pointer) to a specific object in memory. C#中的对象变量是内存中特定对象的引用 (不是指针)。 When you declare 当你声明

Order o2 = new Order();

you are creating a new Order object in the heap, and allocating a reference to that object to your o2 variable. 您正在堆中创建一个新的Order对象,并将对该对象的引用分配给您的o2变量。 When you then state 当你说

o2 = o1;

you are telling the compiler to make o2 a reference to o1. 您要告诉编译器将o2引用为o1。 At this point, the reference to the original o2 object is lost, and the memory for that object will be removed during the next garbage collection sweep. 此时,对原始o2对象的引用将丢失,并且在下一次垃圾回收扫描期间将删除该对象的内存。

Henceforth, both o1 and o2 both reference the same object in memory. 从此以后,o1和o2都引用内存中的同一对象。 To copy information from one object to another, you will need to implement a procedure to instantiate a new destination object and copy all of the data from one object to the other. 要将信息从一个对象复制到另一个对象,您将需要实现一个过程以实例化一个新的目标对象,并将所有数据从一个对象复制到另一个对象。 See the MSDN docs on ICloneable for more info. 有关更多信息,请参见ICloneable上的MSDN文档。

What you are referring to is the difference between value types and reference types. 您所指的是值类型和引用类型之间的区别。 Apparently your Order object is a reference type, I would assume it is a class. 显然您的Order对象是引用类型,我假设它是一个类。

Classes are reference types meaning they are "pointers". 类是引用类型,表示它们是“指针”。 One of the reasons for this is performance as you do not want to copy huge amounts of data every time you assign a variable. 原因之一是性能,因为您不想在每次分配变量时都复制大量数据。

Structures are value types and would be copied in memory when you assign them. 结构是值类型,在分配结构时将其复制到内存中。

You have 2 solutions : 您有2个解决方案:

  • Use a struct instead of class 使用结构代替类
  • Clone your object using either MemberwiseClone if it is very simple, or use your own method if you need to perform a deep clone. 如果非常简单,则使用MemberwiseClone克隆对象;如果需要执行深层克隆,则使用您自己的方法。

This is by Design. 这是设计使然。 If you want to clone and keep the clone independent i would recommend to Implement a "cloning" mechanism on your types. 如果要克隆并保持克隆独立,我建议对您的类型实施“克隆”机制。 This can be ICloneable or even just a constructor that takes an instance and copies values from it. 这可以是ICloneable ,甚至可以是接受实例并从中复制值的构造函数。

Regarding your question 关于你的问题

what would be the best way to accomplish what I want to do? 什么是完成我想做的最好的方法? Which is: store the state of the object, make changes, then revert if necessary 即:存储对象的状态,进行更改,然后在必要时还原

A simple method is to simply serialize the object, eg using XMLSerializer . 一种简单的方法是简单地序列化对象,例如使用XMLSerializer Then if you want to throw away your changes, just deserialize the original object and replace the modified object with the original version. 然后,如果要放弃所做的更改,只需反序列化原始对象,然后将修改后的对象替换为原始版本即可。

Use Structures to accomplish your task, Classes are reference type and Structs are Value type. 使用结构来完成任务,类是引用类型,结构是值类型。 Classes are stored on memory heap Structs are stored on stack. 类存储在内存堆中。结构存储在堆栈中。 for more info search Structs vs Classes and learn differences 有关更多信息,请搜索“结构与类”并了解差异

Objects are, by definition, a 'pointer'; 根据定义,对象是“指针”; they hold a reference to your data, and not the actual data itself. 它们仅引用您的数据,而不是实际数据本身。 You can assign it a value type though and it will give the appearance of holding the data. 不过,您可以为它分配一个值类型,这样看起来就可以保存数据。

As was mentioned above, understanding Value types vs. Reference types is key. 如上所述,理解值类型与引用类型是关键。

Java has no concept of any non-primitive data type other than an object reference; Java没有除对象引用以外的任何非原始数据类型的概念; since almost anything one can do with an object reference involves acting upon the object referred to thereby, the . 因为几乎所有对象引用都可以做,所以涉及作用于该对象. operator in Java . Java中的运算符。 Although .net does have non-primitive value types, most .net languages maintain the convention (different from C and C++, which use -> to access a member of a pointed-to object and . to access a member of a structure) that the same . 尽管.net确实具有非原始值类型,但大多数.net语言都遵循以下约定(与C和C ++不同,它们使用->访问指向对象的成员,而.访问结构的成员)一样. operator is used for both "dereference and access member" and "access value-type member". 运算符用于“取消引用和访问成员”和“访问值类型成员”。

Personally, I dislike Java's "everything is an object reference" design, and .net's decision to have value types and reference types use the same . 就我个人而言,我不喜欢Java的“一切都是对象引用”设计,并且.net决定使用值类型和引用类型的决定是相同的. operator to mean very different things doesn't help, but it is what it is. 表示非常不同的事物的运算符无济于事,而是事实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM