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

问题描述

我刚刚了解到,将通用参数用作out参数的类型会强制该通用类型保持不变。这令我惊讶。我认为out参数与返回类型相同(即,如果通用参数是协变的,则可以将其用作out out参数),因为它们都是a的“输出方法

经过一番调查,我意识到您不能这样做:

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;
    }
}

这说明了为什么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;
    }
}

那么为什么第一个代码段不编译?使用out是否允许F执行返回值无法完成的操作,如果将out object s传递给返回值,则会破坏类型安全性?

我发现this question,这是关于另一种方式的转换-从派生类转换为基类,这显然是不可能的。您不能将返回object方法的返回值分配给类型为string的变量,可以吗?

我要问的是,因为您可以将返回string方法的返回值分配给类型object的变量,所以为什么不能对{{1 }}参数?也就是说,为什么不能将out传递给out object参数?

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

解决方法

使用out参数,该参数像引用ref一样通过引用传递,不同之处在于该值必须在方法末尾赋值,并且在调用之前不需要初始化引用。但这可以在之前初始化,并且方法可以读取初始值

enter image description here

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

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

类似于ref关键字,除了ref要求在传递变量之前先对其进行初始化

由于该方法可以读取变量,因此引用必须为string类型才能起作用。读取块具有协方差,输出块具有协方差,因此参数必须是不变的。

,

众所周知,out参数只是返回值的另一种方式

不正确:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out

作为参数修饰符,它使您可以通过引用而不是通过值将参数传递给方法。

这意味着您正在传递对特定对象的引用。

我想您的答案在这里:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref

通过引用传递引用类型可以使被调用方法替换调用者中引用参数所引用的对象。

因此,当您将对象传递给函数时,您实际上是在进行类型的分配

派生

以及从函数内部进行分配时

基本

,

考虑一下,您可以在c#中执行以下操作:

public static void Out(out string s)
{
    Thread.Sleep(50);
    s = "World";
}

public static void Ref(ref string s)
{
    Console.WriteLine(s); // Hello
    Thread.Sleep(100);
    Console.WriteLine(s); // World
}

string str = "Hello";
new Thread(() => Out(out str)).Start();
new Thread(() => Ref(ref str)).Start();

如果将string str更改为object str是合法的,那么现在str可以是任何类型,如何在Out和Ref方法之间保留引用?

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...