object 是 ref 类型这一事实的冲突

Conflict in the fact that object is a ref type

我读过有关 C# 中的引用和值类型的信息,但不知道在下面的示例中为什么 y = 10 虽然 xy 是引用类型?

object x = 10;
object y = x;
x = 20;
Console.WriteLine(y); //why y = 10 although x and y are reference types?

如果你让我相信原因,我该如何更改 x 和 y 都引用的对象?

让我们暂时忽略 object 类型。当你像那样进行初始化时

SomeType y = x;
如果 SomeType 是引用类型 class,则

y 成为 x 的别名,或者它成为 copy of x 如果 SomeType 是值类型 struct.

可见的情况是SomeType可变的。在引用类型的情况下,更改通过 x 引用的对象的内容也会更改 y,因为它是同一个对象。但是,如果它是副本,则更改 xy.

没有影响

由于您的代码使用包装整数基元的装箱不可变类型的对象,因此此分配

x = 20;

使变量 x 引用一个完全不同的不可变对象。 y的值保持不变。

语句-

Object x = 10

有个特别的名字,叫做拳击。那是将值类型包装在引用类型中。您可能认为这应该创建一个引用。是的你是对的。但这也意味着创建了一个新对象——如文档中所述——

When a value type is boxed, a new object must be allocated and constructed.

https://msdn.microsoft.com/en-us/library/yz2be5wk.aspx

现在当你这样做时 -

object y = x;

Y 和 X 是相同的对象,指向相同的内存位置。这远没问题。但是接下来的声明 -

x = 20;

导致异常。你看,这个语句是另一个装箱,当装箱创建新实例时,这正在创建另一个具有值 20 和 putting/referring 的新对象,该对象具有 X.

因此,Y 指向最后一个内存位置,而 X 指向新的内存位置。

你可以通过访问我上面提到的 link 来理解为什么。

如果你让我相信原因,我怎么能改变 x 和 y 都引用的对象? => 你不能!因为 C# 不支持显式指针,而您使用的是值类型。

但是,如果 X 和 Y 是引用类型(即 Class 对象),那么您可以这样做。

object x = 10;
object y = x;

之后 xy 引用同一个对象:

x, y -> 10

但是当你让 x = 20:

x -> 20
y -> 10

你可以用 class:

包装值
class Ref<T>
{
    public T Value;

    public static implicit operator T(Ref<T> x)
    {
        return x.Value;
    }

    public static implicit operator Ref<T>(T x)
    {
        return new Ref<T>() { Value = x };
    }
}

然后:

Ref<int> x = 10;
Ref<int> y = x;

// x, y -> Ref -> 10

x.Value = 20;

// x, y -> Ref -> 20

Console.WriteLine(y); // y is 20 (or rather y.Value is 20)

我得到了你的答案,这个例子可能会让事情变得更清楚。

class Complex
{
    public int real;
    public int imag;
}

static void Main(string[] args)
{
    Complex c1 = new Complex();
    Complex c2 = new Complex();
    c2.real = 100;
    c2.imag = 100;

    object x = c1;
    object y = x;

    ((Complex)x).imag = 50; //y here is changed

    x = c2; //y here isn't changed because this line makes x is now pointing on sth else which doesn't matter with the object referenced by y

}