我想将一个对象设置为与C#核心中的其他对象值相等,而不是通过引用!
x.len=10;
val y=x;
y.len=x.len*2;
我希望y.len
设置为20,并且x.len
保持不变,但是y.len
和x.len
都为20,我正在寻找一种断开x
的方法]和y
。
我记得在[[VB6中,我们有类似[[ByRef和ByVal之类的东西使我们能够控制此东西,C#Core 3.x中是否有类似的东西?
我想将一个对象设置为等于c#核心中的其他对象值,而不是通过引用!
为此,您需要一个没有在堆上分配的值类型(例如struct),或者对于引用类型,您需要一个深层副本而不是浅层副本。在.Net C#中,默认情况下,所有类都是在堆上分配的,是引用类型,并且在传递对象时,其要么按值引用(这是指向同一内存的另一个指针),要么按引用引用(指向使用ref的指针的指针)关键字)
让我们查看代码
var y=x;
,查看结果,可以安全地假设y和x属于同一类型,但两者均为引用类型。因此,如果value type
不是您的选择,请执行以下操作之一:
通过以下方式创建深层副本:
序列化,最好是二进制,因为它的紧凑性,对于非圆形对象层次结构,序列化工作得很好,当您反序列化然后将其作为新对象时使用复制构造函数,其中一个对象逐个属性复制,逐个字段复制到新分配中
var x = new SomeReadonlyValueType(10);
var y = x; // this is a value copy
y = y.WithLength(x.len * 2); // mutation method
[如果您不想那样做,并且希望x
成为可变类的实例,则需要对该实例进行深度克隆,即]]x.len=10;
val y=x.DeepClone();
y.len=x.len*2;
在这里,它们分离的点非常清晰明了;不过,您需要实现DeepClone()
-没有标准的内置方式可以提供。对于简单的情况,可以用手滚动;对于复杂的情况,序列化是一种流行的方式。
SomeReadonlyValueType
的示例代码:readonly struct SomeReadonlyValueType { public int Length { get; } public int Width { get; } public SomeReadonlyValueType(int length, int width) { Length = length; Width = width; } public override string ToString() => $"{Length} x {Width}"; public SomeReadonlyValueType WithLength(int length) => new SomeReadonlyValueType(length, Width); public SomeReadonlyValueType WithWidth(int width) => new SomeReadonlyValueType(Length, width); }