结构,接口和拳击

可能重复:
结构体实现接口是否安全?

拿这个代码:

interface ISomeInterface { public int SomeProperty { get; } } struct SomeStruct : ISomeInterface { int someValue; public int SomeProperty { get { return someValue; } } public SomeStruct(int value) { someValue = value; } } 

然后我做这个地方:

 ISomeInterface someVariable = new SomeStruct(2); 

在这种情况下盒装SomeStruct

是的。 基本上每当你需要一个引用 ,你只有一个值types的值,价值是盒装的。

这里, ISomeInterface是一个接口,它是一个引用types。 因此, someVariable的值总是一个引用,所以新创build的结构值必须被装箱。

乔恩的观点是真实的,但作为一个侧面说明,这个规则只有一个例外。 仿制药。 如果你有where T : ISomeInterface ,那么这是受限制的 ,并使用一个特殊的操作码 。 这意味着界面可以在没有装箱的情况下使用。 例如:

 public static void Foo<T>(T obj) where T : ISomeInterface { obj.Bar(); // Bar defined on ISomeInterface } 

这不涉及拳击,即使是价值型的T 但是,如果(在同一个Foo )你做:

 ISomeInterface asInterface = obj; asInterface.Bar(); 

然后像以前一样。 约束 适用于T

我想补充一点,希望对Jon和Marc提供的答案有更多的了解

考虑这个非generics方法:

 public static void SetToNull(ref ISomeInterface obj) { obj = null; } 

嗯…设置ref参数为null。 这只适用于参考types,对吗? (好吧,或者为Nullable<T> ;但是让我们忽略这种情况,以保持简单。)所以这个方法编译的事实告诉我们,声明为某种接口types的variables必须被视为引用types。

这里的关键词是“声明为”:考虑这种尝试来调用上述方法:

 var x = new SomeStruct(); // This line does not compile: // "Cannot convert from ref SomeStruct to ref ISomeInterface" -- // since x is declared to be of type SomeStruct, it cannot be passed // to a method that wants a parameter of type ref ISomeInterface. SetToNull(ref x); 

当然,你不能在上面的代码SetToNull x传递给SetToNullx需要声明为一个ISomeInterface ,以便能够传递ref x – 而不是因为编译器神奇地知道SetToNull包含行obj = null 。 但是,这只是强化了我的观点: obj = null行是合法的, 因为声明为ISomeInterface的variables传递给方法是非法的。

换句话说,如果一个variables被声明为一个ISomeInterface ,它可以被设置为null,纯粹和简单。 这是因为接口是引用types – 因此,声明一个对象作为一个接口,并将其分配给值types的对象框的值。

另一方面,现在考虑这个假设的通用方法:

 // This method does not compile: // "Cannot convert null to type parameter 'T' because it could be // a non-nullable value type. Consider using 'default(T)' instead." -- // since this method could take a variable declared as, eg, a SomeStruct, // the compiler cannot assume a null assignment is legal. public static void SetToNull<T>(ref T obj) where T : ISomeInterface { obj = null; } 

MSDN文档告诉我们,结构是有价值的,而不是引用types。 转换成objecttypes的variables时,它们被装箱。 但是这里的核心问题是:接口types的variables呢? 既然接口也可以通过一个类来实现,那么就像Jon Skeet已经说过的那样,这就等于把一个值转换成一个引用types,因此是会发生装箱的。 关于msdn博客的更多讨论