object 是 ref 类型这一事实的冲突
Conflict in the fact that object is a ref type
我读过有关 C# 中的引用和值类型的信息,但不知道在下面的示例中为什么 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
的别名,或者它成为 copy of x
如果 SomeType
是值类型 struct
.
可见的情况是SomeType
是可变的。在引用类型的情况下,更改通过 x
引用的对象的内容也会更改 y
,因为它是同一个对象。但是,如果它是副本,则更改 x
对 y
.
没有影响
由于您的代码使用包装整数基元的装箱不可变类型的对象,因此此分配
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;
之后 x
和 y
引用同一个对象:
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
}
我读过有关 C# 中的引用和值类型的信息,但不知道在下面的示例中为什么 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
的别名,或者它成为 copy of x
如果 SomeType
是值类型 struct
.
可见的情况是SomeType
是可变的。在引用类型的情况下,更改通过 x
引用的对象的内容也会更改 y
,因为它是同一个对象。但是,如果它是副本,则更改 x
对 y
.
由于您的代码使用包装整数基元的装箱不可变类型的对象,因此此分配
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;
之后 x
和 y
引用同一个对象:
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
}