为什么以下在委托中使用协方差的示例无法编译?
Why does the following example using covariance in delegates not compile?
我定义了以下委托类型。一个 returns 一个字符串,一个一个对象:
delegate object delobject();
delegate string delstring();
现在考虑以下代码:
delstring a = () => "foo";
delobject b = a; //Does not compile!
为什么赋值无效?
我不明白。 returns 字符串的方法应该被安全地视为 returns 对象的方法(因为字符串是对象)。
在 C# 4.0 中,以下示例有效。我没有使用委托,而是使用 Func<TResult>
通用类型:
Func<string> a = () => "foo";
Func<object> b = a; //Perfectly legal, thanks to covariance in generics
另外:如果我那样重写它,它会起作用:
delobject b = () => a();
但这和我最初想要的不一样。现在我创建了一个调用另一个方法的新方法。
这不仅仅是一个赋值,如本例所示:
delint a = () => 5;
delobject b = a; //Does not work, but this is OK, since "int" is a value type.
delobject b = () => a(); //This will box the integer to an object.
Func
的类型参数标记为 in
和 out
,因此您可以像往常一样将这些类型分配给另一个。这就是 泛型中的变体 的意思。
您的 delobject
和 delstring
是不同的类型并且它们不是变体,因此您不能将一个分配给另一个。但是对于 delobject
你可以分配一个 returns 派生类型的处理程序,这就是 variance in delegates 的意思。
In the context of method overloading, the signature of a method does not include the return value. But in the context of delegates, the signature does include the return value. In other words, a method must have the same return type as the delegate.
由于 return 类型不 完全 匹配(即 object != string
),赋值无效。
所以你可以
delstring a = () => "foo"; // compiles
delobject b = a; // does not compile
delobject c = () => "foo"; // compiles
正如您所指出的,Func 使用 out
协变地工作,而委托则不然。
委托类型仍然是具体的对象类型。当你写
delegate object delobject();
delegate string delstring();
那么这两种委托类型之间就没有"is a"关系了。您只是创建了两种不同的类型。
就像
class A { public int i; };
class B { public int i; };
A
和 B
之间没有隐式或显式转换,即使没有任何可能的 A
与 [=14] 意义不同=],反之亦然。
Func
中的协变和逆变意味着该具体委托类型的作者已经决定 Func<string>
可以被视为 Func<object>
,但这是委托作者的事情type 可以决定,就像我的 class B
的作者可以决定从 A
.
派生是否更有意义一样
您可以做的是在不创建额外方法的情况下再添加一个间接级别:
delstring a = () => "foo";
delobject b = new delobject(a); // or equivalently, a.Invoke
我定义了以下委托类型。一个 returns 一个字符串,一个一个对象:
delegate object delobject();
delegate string delstring();
现在考虑以下代码:
delstring a = () => "foo";
delobject b = a; //Does not compile!
为什么赋值无效?
我不明白。 returns 字符串的方法应该被安全地视为 returns 对象的方法(因为字符串是对象)。
在 C# 4.0 中,以下示例有效。我没有使用委托,而是使用 Func<TResult>
通用类型:
Func<string> a = () => "foo";
Func<object> b = a; //Perfectly legal, thanks to covariance in generics
另外:如果我那样重写它,它会起作用:
delobject b = () => a();
但这和我最初想要的不一样。现在我创建了一个调用另一个方法的新方法。
这不仅仅是一个赋值,如本例所示:
delint a = () => 5;
delobject b = a; //Does not work, but this is OK, since "int" is a value type.
delobject b = () => a(); //This will box the integer to an object.
Func
的类型参数标记为 in
和 out
,因此您可以像往常一样将这些类型分配给另一个。这就是 泛型中的变体 的意思。
您的 delobject
和 delstring
是不同的类型并且它们不是变体,因此您不能将一个分配给另一个。但是对于 delobject
你可以分配一个 returns 派生类型的处理程序,这就是 variance in delegates 的意思。
In the context of method overloading, the signature of a method does not include the return value. But in the context of delegates, the signature does include the return value. In other words, a method must have the same return type as the delegate.
由于 return 类型不 完全 匹配(即 object != string
),赋值无效。
所以你可以
delstring a = () => "foo"; // compiles
delobject b = a; // does not compile
delobject c = () => "foo"; // compiles
正如您所指出的,Func 使用 out
协变地工作,而委托则不然。
委托类型仍然是具体的对象类型。当你写
delegate object delobject();
delegate string delstring();
那么这两种委托类型之间就没有"is a"关系了。您只是创建了两种不同的类型。
就像
class A { public int i; };
class B { public int i; };
A
和 B
之间没有隐式或显式转换,即使没有任何可能的 A
与 [=14] 意义不同=],反之亦然。
Func
中的协变和逆变意味着该具体委托类型的作者已经决定 Func<string>
可以被视为 Func<object>
,但这是委托作者的事情type 可以决定,就像我的 class B
的作者可以决定从 A
.
您可以做的是在不创建额外方法的情况下再添加一个间接级别:
delstring a = () => "foo";
delobject b = new delobject(a); // or equivalently, a.Invoke