C#修改引用类型对象不';不能反映变化
我有一个C#代码: 为什么此时T的值仍然是20而不是100? 我想T和R指向同一个位置,对它们中任何一个的改变都会相互影响 我不能真正理解引用类型在堆中是如何工作的,请帮助我 为什么在这一点上,T的值仍然是20而不是100 因为您没有修改C#修改引用类型对象不';不能反映变化,c#,object,types,reference,C#,Object,Types,Reference,我有一个C#代码: 为什么此时T的值仍然是20而不是100? 我想T和R指向同一个位置,对它们中任何一个的改变都会相互影响 我不能真正理解引用类型在堆中是如何工作的,请帮助我 为什么在这一点上,T的值仍然是20而不是100 因为您没有修改t 你会想抬头看看的。但是,代码中的情况是,存储在i中的值20被“装箱”,这意味着分配了一个新的引用类型对象,并将值20复制到该对象中 分配r=t时,将该装箱值的引用复制到t。到目前为止,一切顺利 但是,当您分配r=100时,您尚未修改装箱的值。原始装箱值保持不
t
你会想抬头看看的。但是,代码中的情况是,存储在i
中的值20
被“装箱”,这意味着分配了一个新的引用类型对象,并将值20
复制到该对象中
分配r=t
时,将该装箱值的引用复制到t
。到目前为止,一切顺利
但是,当您分配r=100时代码>,您尚未修改装箱的值。原始装箱值保持不变,但现在仅由t
引用
赋值r=100
创建一个全新的装箱值,在堆上分配,并将对该对象的引用复制到变量r
中。这对t
没有影响,它仍然设置为20
的第一个装箱值的参考
为什么在这一点上,T的值仍然是20而不是100
因为您没有修改t
你会想抬头看看的。但是,代码中的情况是,存储在i
中的值20
被“装箱”,这意味着分配了一个新的引用类型对象,并将值20
复制到该对象中
分配r=t
时,将该装箱值的引用复制到t
。到目前为止,一切顺利
但是,当您分配r=100时代码>,您尚未修改装箱的值。原始装箱值保持不变,但现在仅由t
引用
赋值r=100
创建一个全新的装箱值,在堆上分配,并将对该对象的引用复制到变量r
中。这对t
没有影响,它仍然被设置为20
的第一个装箱值的引用。当您将整数值i
设置为对象t
时,装箱发生,并且整数值在箱子内放入堆中
当您将t
设置为r=t
时,此时它们指向堆上的相同引用地址。但是当您使用新的整数值设置r
如r=100
时,会出现新的装箱,并且r
将指向不同的地址
首先,装箱和拆箱是非常昂贵的事情。为什么要将integer设置为object
如果要将整数传递给某个方法并获得更改的值,可以在方法参数中使用ref
关键字
您可以在下面找到示例代码:
public int GetValue() {
int i = 20;
SetNewValue(ref i);
return i;
}
public void SetNewValue(ref int value) {
value = 100;
}
当您将整数值i
设置为对象t
时,将发生装箱,并将方框内的整数值放入堆中
当您将t
设置为r=t
时,此时它们指向堆上的相同引用地址。但是当您使用新的整数值设置r
如r=100
时,会出现新的装箱,并且r
将指向不同的地址
首先,装箱和拆箱是非常昂贵的事情。为什么要将integer设置为object
如果要将整数传递给某个方法并获得更改的值,可以在方法参数中使用ref
关键字
您可以在下面找到示例代码:
public int GetValue() {
int i = 20;
SetNewValue(ref i);
return i;
}
public void SetNewValue(ref int value) {
value = 100;
}
装箱的值类型不是不可变的。它们可以提供方法,这些方法可以改变装箱值,尽管它们中的大多数不这样做。@PetSerAl:有趣。谢谢你澄清这一点。我忽略了这种可能性,因为通常装箱的值是通过System.Object
引用的,这当然不会公开装箱对象的任何底层功能。我没有想到,除了取消装箱之外,完全可以访问该值,更不用说修改它了。但快速测试表明,通过反射,实际上可以访问装箱值类型的成员并实际操作它。我认为内部机制(例如,一个运行的计时器)也可以做到这一点。我会编辑来修正这个错误。事实上,当我写这篇文章的时候,我并没有考虑反射。可以调用接口方法,而无需取消绑定对象。例如:在装箱的列表上调用IEnumerator.MoveNext
。枚举器
将装箱的枚举器前进到下一项。@PetSerAl:是的,这是进入装箱对象的另一条路径。有趣的是,我跟进了我的“运行计时器”场景,发现可变值类型中的async
方法可能不好(*)。也就是说,由于生成的状态引擎为每个wait
创建了一个新的值副本,因此,如果从某个装箱值的类型中的接口方法启动计时器,则保留原始装箱值引用的代码将看不到任何更改。如果操作是在单个线程中完成的(例如,thread.Sleep()
,并对值进行了更改),(*)也就是说,首先比可变值类型更糟糕。:)装箱的值类型不是不可变的。它们可以提供方法,这些方法可以改变装箱值,尽管它们中的大多数不这样做。@PetSerAl:有趣。谢谢你澄清这一点。我忽略了这种可能性,因为通常装箱的值是通过System.Object
引用的,这当然不会公开装箱对象的任何底层功能。我没有想到,除了取消装箱之外,完全可以访问该值,更不用说修改它了。但快速测试表明,通过反射,实际上可以访问装箱值类型的成员并实际操作它。我想在