我刚刚了解到将泛型参数作为out参数类型会强制该泛型类型保持不变。这让我很惊讶。我认为out参数被视为与返回类型相同(即如果泛型参数是协变的,那么它可以用作out输出参数),因为它们都是方法的“输出”。
经过一番调查,我意识到你不能这样做:
public class Program {
public static void Main() {
// cannot convert from 'out object' to 'out string'
F(out object s); // passing an out object
}
public static void F(out string o) {
o = null;
}
}
Run Code Online (Sandbox Code Playgroud)
这解释了为什么out参数必须是不变的。但是,我仍然不明白为什么你不能这样做。众所周知,out参数只是返回值的另一种方式。F可以用返回值重写,它会起作用:
// This is the semantically equivalent version of the above, just without "out"
public class Program {
public static void Main() {
object s = F();
}
public static string F() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
那么为什么第一个代码片段不能编译呢?使用outallow是否可以F做一些不能用返回值完成的事情,如果out object s传递给它会破坏类型安全?
我发现了这个问题,这是关于从派生类转换为基类的另一种方式,这显然是不可能的。您不能将返回 a 的方法的返回值分配给object类型为 的变量,对string吗?
我要问的是,既然您可以将返回string到 type 变量的方法的返回值分配给它object,那么为什么不能对out参数执行相同的操作呢?也就是说,为什么不能将 an 传递out object给out string参数?
我还阅读了docs和spec,但他们从未提及您必须将完全相同的类型传递给out参数这一事实,更不用说解释为什么必须这样做了。
与out参数一样,参数通过引用传递ref,区别在于必须在方法结束时分配值,并且在调用之前不需要初始化引用。但是它可以在之前被初始化并且方法可以读取初始值。
来自文档:https : //docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
out 关键字导致参数通过引用传递
类似于 ref 关键字,不同之处在于 ref 要求变量在传递之前进行初始化
由于该方法可以读取变量,因此引用必须是工作类型string。读取阻止协方差,输出阻止逆变,因此参数必须是不变的。