对象是引用类型这一事实存在冲突

本文关键字:事实 存在 冲突 引用类型 对象 | 更新日期: 2023-09-27 18:06:04

我读过c#中的ref和值类型,但在下面的例子中不知道为什么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别名;如果SomeType是值类型struct,则它变为x副本

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

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

x = 20;

使得变量CCD_ 17引用完全不同的不可变对象。y的值保持不变。

object x = 10;
object y = x;

之后xy引用相同的对象:

x, y -> 10

但当你让x = 20:

x -> 20
y -> 10

您可以使用类包装值:

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)

语句-

Object x = 10

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

当一个值类型被装箱时,必须分配和构造一个新对象。

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

现在当你这样做-

object y = x;

Y和X是指向相同内存位置的同一对象。走这么远还可以。但下一个声明-

x = 20;

导致异常。你看,这个语句是另一个装箱,当装箱创建新实例时,这是创建另一个值为20的新对象,并用X.放置/引用它

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

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

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

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

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

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
}