再次在界面中结构;为什么我可以像上课一样使用它



为什么我可以通过((I(o(使用类似类的结构。套装(5, 5(;它输出 5,5是的,o 是对象,但我不能 ((I(s(。套装(4, 4(;输出 1、1为什么((I(s(。Set(4, 4( 是输出不变的值,但 ((I(o(。设置(5, 5( 输出已更改?

我知道我的代码隐式地将 (引用( s 转换为 I(引用(。问题也在代码注释中。

    interface I
    {
        void Set(int x, int y);
    }
    public struct S : I
    {
        int x, y;
        public S(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public void Set(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public override string ToString()
        {
            return String.Format("{0} {1}", x, y);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                S s = new S(1, 1);
                Console.WriteLine(s);
                object o = s;
                ((I)o).Set(5, 5);
                Console.WriteLine(o); // Why this works like class and outputs 5,5 instead of 1,1? 
             ((I)s).Set(4, 4); // why i can`t change reference.  why it outputs 1,1 instead of 4,4
            }
            catch { }
        }
    }

因为什么时候

((I)s).Set(4, 4)

被称为,发生的事情是

1( ((

I(s( 将结构转换为对象(装箱(

2(Set 方法将更改应用于该对象(后来它被垃圾回收器处理,因为没有引用指向它(,但结构保持不变

(I(o( 是否将一个引用类型强制转换为另一个引用类型,但对象保持不变。

从这里得到解释:https://blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-structs-and-interface/

当您进行强制转换时(I)s通过复制s创建S的另一个实例,并将其放入堆中,因为接口是引用类型。所以此时你有两个S实例:一个在堆栈中,另一个在堆中。

因此,当您执行((I)s).Set(4, 4);时,您正在更改第二个,即堆中的那个。

最后Console.WriteLine(s);打印出第一个,堆栈中的那个。

要获得正确的输出,您必须执行以下操作:

var i = (I)s;
i.Set(4, 4);
Console.WriteLine(i);

相关内容

最新更新