gpt4 book ai didi

c# - 装箱后更改结构

转载 作者:太空狗 更新时间:2023-10-29 23:14:42 26 4
gpt4 key购买 nike

我有以下代码:

//Interface defining a Change method
internal interface IChangeBoxedPoint
{
void Change(Int32 x, Int32 y);
}

internal struct Point : IChangeBoxedPoint
{
private Int32 m_x, m_y;

public Point(Int32 x, Int32 y)
{
m_x = x;
m_y = y;
}

public void Change(Int32 x, Int32 y)
{
m_x = x; m_y = y;
}

public override string ToString()
{
return String.Format("({0}, {1})", m_x.ToString(), m_y.ToString());
}
}

public class Program
{
static void Main(string[] args)
{
Point p = new Point(1, 1);

Console.WriteLine(p); // "(1, 1)"

p.Change(2, 2);
Console.WriteLine(p); // "(2, 2)"

Object o = p;
Console.WriteLine(o); // "(2, 2)"

((Point)o).Change(3, 3);
Console.WriteLine(o); // "(2, 2)"

//Boxes p, changes the boxed object and discards it
((IChangeBoxedPoint)p).Change(4, 4);
Console.WriteLine(p); // "(2, 2)"

IChangeBoxedPoint h = ((IChangeBoxedPoint)p);
h.Change(4, 4);
//Boxed p is not yet garbage collected
Console.WriteLine(p);// "(2, 2)"

Console.WriteLine(h); //"(4, 4)" //After this line boxed p is garbage collected

//Changes the boxed object and shows it
((IChangeBoxedPoint)o).Change(5, 5);
Console.WriteLine(o); // "(5, 5)"

Console.Read();
}
}

这是 CLR 通过 C# 4th ed(第 138 页)修改的示例。书上是这么说的

((IChangeBoxedPoint)p).Change(4, 4);
Console.WriteLine(p); // "(2, 2)"

将输出“(2, 2)”,因为装箱的 p 将立即被垃圾回收。但是,这样做的真正原因难道不是因为更 retrofit 箱变量的值只会更改堆上对象中的值,在这种情况下,p 保持不变吗?为什么盒装p得到垃圾回收有什么关系?

我相信这与它无关,因为在这段代码中:

IChangeBoxedPoint h = ((IChangeBoxedPoint)p);
h.Change(4, 4);
//Boxed p is not yet garbage collected
Console.WriteLine(p);// "(2, 2)"

Console.WriteLine(h); // //After this line boxed p is garbage collected

我们正在装箱 p,在装箱的 p 上调用 change 方法,通过在 Console.WriteLine(h); 中使用它使 h 保持事件状态,但是 Console.WriteLine(p); 仍然会输出“(2, 2)”。

有谁知道为什么作者写的是装箱的p被垃圾回收是p没有改变的原因,因为这似乎根本不是真的。

最佳答案

你描述的方式,书上写错了*,垃圾回收过程完全不影响进程。事实上,垃圾收集器每隔一段时间就会运行一次,它很少会在这两个语句之间处于事件状态。

原因是装箱创建了该结构的另一个副本,因此我们现在正在处理该结构的两个实例。原始的 p 和框中的 h。当 h 改变时,原来的 p 不受影响。

C# 中的结构具有值语义,这意味着它们在许多情况下会自动复制,例如赋值、作为参数传递给函数和装箱。通过修改副本而不是原始结构很容易出错。为了避免这种情况,结构应该始终是不可变的

*) 引用@KirillShlenskiy 的话,我不能再说这本书是错的,因为事实并非如此。是对的,但是解释的有点乱,容易被误解。

关于c# - 装箱后更改结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24463905/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com