【发布时间】:2019-07-22 14:25:36
【问题描述】:
在 Eric Lippert 的关于协变和逆变的博文中,以及在 C# in a Nutshell 等书籍中,都指出:
如果您要定义通用委托类型,最好的做法是:
- 将仅用于返回值的类型参数标记为协变(out)。
- 将仅用于参数的任何类型参数标记为逆变 (in)。
这样做可以让转化通过尊重自然而然地进行 类型之间的继承关系。
所以我正在试验这个,我发现了一个相当奇怪的例子。
使用这个类层次结构:
class Animal { }
class Mamal : Animal { }
class Reptile : Animal { }
class Dog : Mamal { }
class Hog : Mamal { }
class Snake : Reptile { }
class Turtle : Reptile { }
在尝试使用方法组到委托的转换和委托到委托的转换时,我编写了以下代码 sn-p:
// Intellisense is complaining here
Func<Dog, Reptile> func1 = (Mamal d) => new Reptile();
// A local method that has the same return type and same parameter type as the lambda expression.
Reptile GetReptile(Mamal d) => new Reptile();
// Works here.
Func<Dog, Reptile> func2 = GetReptile;
为什么方差规则适用于本地方法而不适用于 lambda 表达式?
鉴于 lambda 表达式是代替委托实例编写的未命名方法,并且编译器会立即将 lambda 表达式转换为:
- 委托实例。
- 表达式树,表达式类型。
我假设:
Func<Dog, Reptile> func1 = (Mamal d) => new Reptile();
正在发生的事情是从类似的转换:
Func<Mamal, Reptile> => Func<Dog, Reptile>.
从委托到委托的差异规则与从方法组到委托的差异规则是否不同?
【问题讨论】:
标签: c# delegates covariance contravariance