Sek*_*hat 43 c# struct boxing interface value-type
可能重复:
结构实现接口是否安全?
拿这个代码:
interface ISomeInterface
{
public int SomeProperty { get; }
}
struct SomeStruct : ISomeInterface
{
int someValue;
public int SomeProperty { get { return someValue; } }
public SomeStruct(int value)
{
someValue = value;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在某个地方这样做:
ISomeInterface someVariable = new SomeStruct(2);
Run Code Online (Sandbox Code Playgroud)
就是SomeStruct
在这种情况下,盒装?
Mar*_*ell 67
乔恩的观点是正确的,但作为旁注,该规则有一个轻微的例外; 仿制药.如果你有where T : ISomeInterface
,那么这是受约束的,并使用特殊的操作码.这意味着界面可以在没有装箱的情况下使用.例如:
public static void Foo<T>(T obj) where T : ISomeInterface {
obj.Bar(); // Bar defined on ISomeInterface
}
Run Code Online (Sandbox Code Playgroud)
这并没有涉及拳击,即使是价值型T
.但是,如果(相同Foo
)你这样做:
ISomeInterface asInterface = obj;
asInterface.Bar();
Run Code Online (Sandbox Code Playgroud)
那个盒子和以前一样.该限制 只直接应用于T
.
Jon*_*eet 54
是的.基本上,只要您需要引用并且只获得值类型值,该值就会被装箱.
这ISomeInterface
是一个接口,它是一个引用类型.因此,值someVariable
始终是引用,因此必须将新创建的struct值加框.
我正在补充这一点,希望能更多地了解 Jon和Marc提供的答案.
考虑这种非通用方法:
public static void SetToNull(ref ISomeInterface obj) {
obj = null;
}
Run Code Online (Sandbox Code Playgroud)
嗯...将ref
参数设置为null.那只是参考类型,对吗?(好吧,或者对于a Nullable<T>
;但是让我们忽略这种情况以保持简单.)因此,此方法编译的事实告诉我们,声明为某种接口类型的变量必须被视为引用类型.
这里的关键短语是"声明为":考虑这种尝试调用上述方法:
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);
Run Code Online (Sandbox Code Playgroud)
当然,您无法传递x
上述代码的原因SetToNull
是x
需要声明ISomeInterface
为您能够传递ref x
- 而不是因为编译器神奇地知道SetToNull
包含该行obj = null
.但是在某种程度上只是强调了我的观点:该obj = null
行是合法的,因为将未声明的变量传递给该方法是违法的.ISomeInterface
换句话说,如果变量声明为an ISomeInterface
,则可以将其设置为null,纯粹且简单.这是因为接口是引用类型 - 因此,将对象声明为接口并将其分配给值类型对象框的值.
另一方面,现在考虑这个假设的通用方法:
// 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, e.g., a SomeStruct,
// the compiler cannot assume a null assignment is legal.
public static void SetToNull<T>(ref T obj) where T : ISomeInterface {
obj = null;
}
Run Code Online (Sandbox Code Playgroud)