为什么我可以通过((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);