提问人:Mertez 提问时间:3/19/2020 最后编辑:Kate OrlovaMertez 更新时间:3/19/2020 访问量:911
C# 核心 3.1 ByRef 和 ByVal
C# Core 3.1 ByRef and ByVal
问:
我想在 C# 核心中设置一个对象等于其他对象值,而不是通过引用!
x.len=10;
val y=x;
y.len=x.len*2;
我希望设置为 20 并保持不变,但两者都是 20,我正在寻找一种断开连接的方法。y.len
x.len
y.len
x.len
x
y
我记得在 VB6 中,我们有类似 ByRef 和 ByVal 的东西,它让我们能够控制这个东西,在 C# Core 3.x 中也有类似的东西吗?
答:
我想在 c# core 中设置一个对象等于其他对象值,而不是通过引用!
为此,您需要一个值类型,例如 struct,它不是在堆上分配的,或者对于引用类型,您需要一个深拷贝而不是浅拷贝。 在 .Net C# 中,默认情况下,所有类都是在堆上分配的,都是引用类型,当传递对象时,它要么按值引用(这是指向同一内存的另一个指针),要么按引用引用(指向指针的指针, 这是使用 ref 和 out 关键字)
让我们回顾一下代码
var y=x;
,从结果来看,可以安全地假设 y 和 x 属于同一类型,但两者都是参考类型。因此,如果不适合您,请执行下列操作之一:value type
通过以下方式创建深层副本:
- 序列化,最好是二进制作为其紧凑,对于非循环对象层次结构序列化效果很好,当你反序列化时,它就是一个新对象
- 使用 copy 构造函数,其中对象逐个属性、逐个字段复制到新分配中
一旦你这样做了,你会发现一个对象在修改属性时不会修改另一个对象的浅层复制
评论
IClone<T>
“断开”事物的最简单方法是首先让它们成为价值类型;如果是某种 ,那么你所拥有的已经可以工作了,但是:可变结构通常是一个糟糕的想法,会引起各种混乱,所以实际上我会在那里使用不同的 API:x
struct
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);
}
评论
x
y