简体   繁体   English

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

[英]Struct in interface again; Why can I use it like class?

Why can I use struct like class by ((I)o).Set(5, 5); 为什么我可以使用((I)o).Set(5,5); It outputs 5,5 Yes, o is object but i can`t ((I)s).Set(4, 4); 它输出5,5是,o是对象,但我不能((I)s.Set(4,4); // output 1, 1 Why ((I)s).Set(4, 4) is output unchanged value but ((I)o).Set(5, 5) outputs changed? //输出1,1为什么((I)s).Set(4,4)的输出保持不变,而((I)o).Set(5,5)的输出却改变了?

I know that my code implicitly casting (citation) s to I (citation). 我知道我的代码隐式地将(引用)转换为I(引用)。 Question is in code comments also. 问题也在代码注释中。

    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 { }

        }
    }

When you do casting (I)s another instance of S is created by copying s and placed into heap as interfaces are reference types. 当您进行强制转换(I)s ,通过复制s创建S (I)s另一个实例,并将其放入堆中,因为接口是引用类型。 So at this point you have two instances of S : one in the stack and the other in the heap. 因此,此时您有两个S实例:一个在堆栈中,另一个在堆中。

Consequently when you do ((I)s).Set(4, 4); 因此,当您执行((I)s).Set(4, 4); you are changing the second, the one in the heap. 您正在更改第二个,即堆中的一个。

Finally Console.WriteLine(s); 最后Console.WriteLine(s); is printing out the first, the one in the stack. 正在打印第一个,即堆栈中的第一个。

To get correct output you must do: 要获得正确的输出,您必须执行以下操作:

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

Because when 因为什么时候

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

is called, what happens is 被称为发生了什么事

1) ((I)s) converts the struct into an object (boxing) 1)((I)s)将结构转换为对象(装箱)

2) the Set method applies the changes to that object (and later it gets disposed of by garbage collector because no reference points to it), but the struct remains unchanged 2)Set方法将更改应用于该对象(后来由于没有引用指向该对象而被垃圾收集器丢弃),但结构保持不变

Whether the ((I)o) casts one reference type into another, but the object stays the same. ((I)o)是否将一种引用类型转换为另一种引用类型,但对象保持不变。

Took explanation from here: https://blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-structs-and-interface/ 从这里进行了解释: https : //blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-structs-and-interface/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM