【问题标题】:Copy stucture's ref-type members by value按值复制结构的引用类型成员
【发布时间】:2013-01-22 19:28:41
【问题描述】:

我有一个结构和一个类

public class MyClass
{
    public string name;
}

public struct MyStructure
{
    public MyClass classValue;
    public int intValue;
    public MyStructure(MyClass classValue, int intValue)
    {
        this.classValue = classValue;
        this.intValue = intValue;
    }
}

我在其他地方写了以下代码:

MyClass class1 = new MyClass() { name = "AA" };
MyStructure struct1 = new MyStructure(class1, 4);
MyStructure struct2 = struct1;
struct1.classValue.name = "BB";  //struct2.classValue.name also change!

在这种情况下,如何确保结构的每个引用类型成员都按值复制?

【问题讨论】:

  • struct 不是 myStructure 的好选择。这就是问题的根源。
  • @HenkHolterman 是正确的。为什么你想要struct 语义呢?使用structs 有充分的理由,但情况非常具体。
  • @HenkHolterman 也许你应该解释一下为什么你认为MyStructure 不应该是struct。它由一个对象引用和一个Int32 组成。正如它所写的那样,它是一个可变的struct,但这与问题无关。它可以变得不可变。 KeyValuePair<int, MyClass> 也有同样的行为,struct
  • @ChristopherPfohl 更改为class 对他有帮助吗?不。他似乎想要一个深拷贝,而struct 并没有给他那个。一个类甚至没有给他一个浅拷贝(它只是给同一个对象一个新的引用),所以它并没有真正接近他想要的。听起来他选择了struct,因为他想要按值复制的语义。这就是选择struct的正当理由。

标签: c# value-type reference-type


【解决方案1】:

您的MyStructureMyClass 类型的对象引用和int (Int32) 组成。任务

MyStructure struct2 = struct1;

只复制那些数据、引用和整数。没有创建 MyClass 的新实例。这是你无法改变的。

如果你想复制,你可以说

MyStructure struct2 = new MyStructure(
    new MyClass { name = struct1.classValue, },
    struct1.intValue
    );

当然,如果你需要做很多事情,你可以写一个Clone() 方法来做这件事。但是您必须记住使用Clone 方法,而不仅仅是分配。

(顺便说一句,MyStructure 是一个“可变结构”。很多人不鼓励他们。如果将MyStructure 的字段标记为readonly,我认为“很多人”会满意。)

补充:另见Answer to Can structs contain references to reference types in C#

【讨论】:

  • 结构体拥有允许分段突变的字段远不如结构体将状态封装在可能发生突变的对象中危险。对于结构来说,将可变类对象的 identity 作为其状态的一部分是很好的(例如 KeyValuePair<string, Form> 就是这种情况,但是结构将可变对象的状态封装为一部分他们自己的状态往往具有非常混乱的语义。
【解决方案2】:

赋值运算符不会深度复制结构内的引用类型字段。但是,您可以创建自己的复制构造函数来手动执行深度复制:

public MyStructure(MyStructure structure)
{
    classValue = new MyClass() { name = structure.classValue.name };
    intValue = structure.intValue;
}

然后调用复制构造函数:

MyStructure struct2 = new MyStructure(struct1);

或者,您可以将MyClass 更改为结构。

【讨论】:

  • 我也想过把MyClass改成结构体。但似乎他需要“变异”MyClass 实例,因此将其设为struct 会导致许多人认为是邪恶的“可变结构”。
  • 嵌套在可变暴露字段结构中的结构可以很好地工作;从性能的角度来看,可以访问内部结构的字段,就好像它们只是外部结构的字段一样。封装为其他类型的属性或只读字段的结构效果较差,系统必须制作此类结构的冗余副本才能访问其任何属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多