结构,接口和拳击
可能重复:
结构体实现接口是否安全?
拿这个代码:
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
传递给SetToNull
是x
需要声明为一个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。 转换成object
types的variables时,它们被装箱。 但是这里的核心问题是:接口types的variables呢? 既然接口也可以通过一个类来实现,那么就像Jon Skeet已经说过的那样,这就等于把一个值转换成一个引用types,因此是会发生装箱的。 关于msdn博客的更多讨论