装箱后改变结构

Bac*_*ave 5 c# boxing

我有以下代码:

//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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是CLR通过C#4th ed(第138页)的修改示例.在书中它说

((IChangeBoxedPoint)p).Change(4, 4);
Console.WriteLine(p); // "(2, 2)"
Run Code Online (Sandbox Code Playgroud)

将输出"(2,2)",因为盒装的p将立即被垃圾收集.但是,实际的原因是,更改盒装变量的值只会改变堆上对象的值,在这种情况下,保持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
Run Code Online (Sandbox Code Playgroud)

我们正在拳击p,在盒装p上调用change方法,通过使用它来保持h存活Console.WriteLine(h);,但是Console.WriteLine(p);仍然会输出"(2,2)".

有谁知道为什么作者写道盒装p被垃圾收集是p没有改变的原因,因为它似乎根本不是真的.

And*_*bel 3

你描述的方式,书上是错误的*,垃圾收集过程根本不影响进程。事实上,垃圾收集器会定期运行,并且它很少在这两个语句之间处于活动状态。

原因是装箱创建了该结构的另一个副本,因此我们现在正在使用该结构的两个实例。原件ph盒子里的。h更改时,原始内容p不受影响。

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

*)引用@KirillShlenskiy 的话,我不能再说这本书是错误的,因为它不是。这是正确的,但解释有点混乱,很容易被误解。