对象是引用类型这一事实存在冲突
本文关键字:事实 存在 冲突 引用类型 对象 | 更新日期: 2023-09-27 18:06:04
我读过c#中的ref和值类型,但在下面的例子中不知道为什么y = 10
,尽管x
和y
是引用类型?
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
,因为它是同一个对象。但是,如果是副本,则更改x
对y
没有影响。
由于您的代码使用装箱不可变类型的对象包装整数基元,因此此分配
x = 20;
使得变量CCD_ 17引用完全不同的不可变对象。y
的值保持不变。
object x = 10;
object y = x;
之后x
和y
引用相同的对象:
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
}