C#Core 3.1 ByRef和ByVal

问题描述 投票:5回答:2

我想将一个对象设置为与C#核心中的其他对象值相等,而不是通过引用!

x.len=10;
val y=x;
y.len=x.len*2;

我希望y.len设置为20,并且x.len保持不变,但是y.lenx.len都为20,我正在寻找一种断开x的方法]和y

我记得在[[VB6中,我们有类似[[ByRef和ByVal之类的东西使我们能够控制此东西,C#Core 3.x中是否有类似的东西?

c# asp.net-core pass-by-reference pass-by-value
2个回答
2
投票
我想将一个对象设置为等于c#核心中的其他对象值,而不是通过引用!

为此,您需要一个没有在堆上分配的值类型(例如struct),或者对于引用类型,您需要一个深层副本而不是浅层副本。在.Net C#中,默认情况下,所有类都是在堆上分配的,是引用类型,并且在传递对象时,其要么按值引用(这是指向同一内存的另一个指针),要么按引用引用(指向使用ref的指针的指针)关键字)

让我们查看代码

var y=x;,查看结果,可以安全地假设y和x属于同一类型,但两者均为引用类型。因此,如果value type不是您的选择,请执行以下操作之一:

通过以下方式创建深层副本:

序列化,最好是二进制,因为它的紧凑性,对于非圆形对象层次结构,序列化工作得很好,当您反序列化然后将其作为新对象时

    使用复制构造函数,其中一个对象逐个属性复制,逐个字段复制到新分配中
  • 一旦完成操作,当属性被修改时,您会发现一个对象不一样的浅表副本不会修改另一个对象

  • 1
    投票
    将已经起作用,但是:可变结构通常是一个可怕的主意,并且会引起各种混乱,因此实际上我会选择另一种方法API在那里:

    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); }
    © www.soinside.com 2019 - 2024. All rights reserved.