我添加这个是为了希望对 Jon 和 Marc 提供的答案有更多的了解。
考虑这种非泛型方法:
public static void SetToNull(ref ISomeInterface obj) {
obj = null;
}
嗯...将ref
参数设置为空。那可能只是参考类型,对吗?(好吧,或者对于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);
当然,您无法将x
上述代码传递给的原因SetToNull
是x
需要将其声明ISomeInterface
为您才能通过ref x
- 而不是因为编译器神奇地知道SetToNull
包含行obj = null
. 但是以某种方式强化了我的观点:该obj = null
行是合法的,正是因为将未声明为 an的变量传递给方法是非法的。ISomeInterface
换句话说,如果一个变量被声明为一个ISomeInterface
,它可以被设置为空,纯粹和简单。那是因为接口是引用类型——因此,将对象声明为接口并将其分配给值类型对象框该值。
现在,另一方面,考虑这个假设的泛型方法:
// 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;
}