为什么我不能从“out BaseClass”转换为“out DerivedClass”?

Swe*_*per 6 c# out

我刚刚了解到将泛型参数作为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 objectout string参数?

我还阅读了docsspec,但他们从未提及您必须将完全相同的类型传递给out参数这一事实,更不用说解释为什么必须这样做了。

Jas*_*son 5

out参数一样,参数通过引用传递ref,区别在于必须在方法结束时分配值,并且在调用之前不需要初始化引用。但是它可以在之前被初始化并且方法可以读取初始值

在此处输入图片说明

来自文档:https : //docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier

out 关键字导致参数通过引用传递

类似于 ref 关键字,不同之处在于 ref 要求变量在传递之前进行初始化

由于该方法可以读取变量,因此引用必须是工作类型string。读取阻止协方差,输出阻止逆变,因此参数必须是不变的。