为什么我不能从 'out BaseClass' 转换为 'out DerivedClass'?
Why can't I convert from 'out BaseClass' to 'out DerivedClass'?
我刚刚了解到,将泛型参数作为 out
参数的类型会强制该泛型类型不变。这让我感到惊讶。我认为 out
参数的处理方式与 return 类型相同(即,如果泛型参数是协变的,那么它可以用作 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;
}
}
这解释了为什么 out
参数必须是不变的。但是,我仍然不明白为什么你不能这样做。众所周知,out
参数只是 return 值的另一种方式。 F
可以用 return 值重写,它会起作用:
// 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
做一些不能用 return 值做的事情,如果将 out object s
传递给它会破坏类型安全?
我发现 this question,这是关于转换另一种方式 - 从派生 class 到基础 class,这显然是不可能的。您不能将 return 是 object
的方法的 return 值分配给 string
类型的变量,可以吗?
我要问的是,既然你可以将 return s string
的方法的 return 值分配给 object
类型的变量,为什么你不能用 out
参数做同样的事情吗?也就是说,为什么不能将 out object
传递给 out string
参数?
我也阅读了 docs and the spec,但他们从未提及必须将完全相同的类型传递给 out
参数这一事实,更不用说 explain 为什么你必须这样做。
with out
parameters the argument are passed by reference just like ref
, 不同之处在于必须在方法结束时赋值并且不需要初始化引用在打电话之前。但是可以先初始化,方法可以读取初始值.
来自文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
The out keyword causes arguments to be passed by reference
It is like the ref keyword, except that ref requires that the variable be initialized before it is passed
由于该方法可以读取变量,因此引用必须是 string
类型才能工作。读取块协变和输出块逆变,因此参数必须是不变的。
As is commonly known, out parameters are just another way of returning a value
不正确:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out
As a parameter modifier, which lets you pass an argument to a method by reference rather than by value.
这意味着您正在传递对特定对象的引用。
我想你的答案在这里:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller.
因此,当您将对象传递给函数时,您实际上是在进行类型赋值
派生 <- 基础
当你从函数内部赋值时
基础 <- 派生
想想你可以在 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方法之间的引用?
我刚刚了解到,将泛型参数作为 out
参数的类型会强制该泛型类型不变。这让我感到惊讶。我认为 out
参数的处理方式与 return 类型相同(即,如果泛型参数是协变的,那么它可以用作 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;
}
}
这解释了为什么 out
参数必须是不变的。但是,我仍然不明白为什么你不能这样做。众所周知,out
参数只是 return 值的另一种方式。 F
可以用 return 值重写,它会起作用:
// 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
做一些不能用 return 值做的事情,如果将 out object s
传递给它会破坏类型安全?
我发现 this question,这是关于转换另一种方式 - 从派生 class 到基础 class,这显然是不可能的。您不能将 return 是 object
的方法的 return 值分配给 string
类型的变量,可以吗?
我要问的是,既然你可以将 return s string
的方法的 return 值分配给 object
类型的变量,为什么你不能用 out
参数做同样的事情吗?也就是说,为什么不能将 out object
传递给 out string
参数?
我也阅读了 docs and the spec,但他们从未提及必须将完全相同的类型传递给 out
参数这一事实,更不用说 explain 为什么你必须这样做。
with out
parameters the argument are passed by reference just like ref
, 不同之处在于必须在方法结束时赋值并且不需要初始化引用在打电话之前。但是可以先初始化,方法可以读取初始值.
来自文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
The out keyword causes arguments to be passed by reference
It is like the ref keyword, except that ref requires that the variable be initialized before it is passed
由于该方法可以读取变量,因此引用必须是 string
类型才能工作。读取块协变和输出块逆变,因此参数必须是不变的。
As is commonly known, out parameters are just another way of returning a value
不正确:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out
As a parameter modifier, which lets you pass an argument to a method by reference rather than by value.
这意味着您正在传递对特定对象的引用。
我想你的答案在这里:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller.
因此,当您将对象传递给函数时,您实际上是在进行类型赋值
派生 <- 基础
当你从函数内部赋值时
基础 <- 派生
想想你可以在 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方法之间的引用?