Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#修改引用类型对象不';不能反映变化_C#_Object_Types_Reference - Fatal编程技术网

C#修改引用类型对象不';不能反映变化

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时,您尚未修改装箱的值。原始装箱值保持不

我有一个C#代码:

为什么此时T的值仍然是20而不是100?

我想T和R指向同一个位置,对它们中任何一个的改变都会相互影响

我不能真正理解引用类型在堆中是如何工作的,请帮助我

为什么在这一点上,T的值仍然是20而不是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
引用的,这当然不会公开装箱对象的任何底层功能。我没有想到,除了取消装箱之外,完全可以访问该值,更不用说修改它了。但快速测试表明,通过反射,实际上可以访问装箱值类型的成员并实际操作它。我想在