我添加这个是为了希望更多地了解 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 行是合法的作为方法的ISomeInterface。
换句话说,如果一个变量被声明为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;
}