具有多个参数的Func方差

时间:2016-03-15 09:18:02

标签: c# covariance func

在我们的代码中尝试了类似的东西,但它失败了:

Func<Employee, Employee> _myFunc;

void Main()
{
    Func<Employee, Employee> test1  = _myFunc;//Ok
    Func<Employee, Person> test2  = _myFunc;//Ok
    Func<Person, Employee> test3 = _myFunc;//Fails
    Func<Person, Person> test4  = _myFunc;//Fails
}

public class Person { }
public class Employee : Person { }

最后两个案例给出了这个错误:

  

无法将System.Func<Employee, Employee>类型隐式转换为System.Func<Person, Employee>。存在显式转换(您是否错过了演员?)

知道为什么吗?

4 个答案:

答案 0 :(得分:12)

如果您查看Func<T, TResult>的签名,您会看到输入参数(在这种情况下为T)是逆变,并且返回类型({ {1}})是协变

TResult

逆变法基本上是关于能够将“更大”类型传递给期望“更小”类型的方法,其中协方差恰恰相反。

Eric Lippert提出这个beautifully and elegantly (emphasis mine)

  

如果使用引用构造,泛型类型I 协变(在T中)   类型参数保留赋值兼容性的方向。它   是逆变(在T中),如果反转分配方向   兼容性即可。如果既不不变。就此而言,我们   简单地说是一个需要T的投影   并产生我是一个协变/逆变/不变投影。

答案 1 :(得分:2)

因为<img src="http://example.com/cat.png" <img src="http://example.com/dog.png" <img src="http://example.com/rat.png" 定义为

Func<T, TResult>

正如你所看到的,第二个参数(public delegate TResult Func<in T, out TResult>(T arg); )确实是一个协变,但第一个参数(TResult,它是函数的输入)实际上是一个逆变(你只能用不太衍生的东西喂它。

T很好,因为它与签名匹配,而Func<Employee, Person>失败,因为它不是。

请参阅MSDN

答案 2 :(得分:0)

好的,我想我现在明白了:

void Main()
{
    Func<Employee, Employee> getEmployeesBoss = (Employee employee) => {return employee.Boss;};
    //This works as it expects a Person to be returned and employee.Boss is a person.
    Func<Employee, Person> getEmployeesBoss1 = getEmployeesBoss;
    //This fails as I could pass a non Employee person to this func which would not work.
    Func<Person, Employee> getEmployeesBoss2 = getEmployeesBoss;
}

class Person {} 
class Employee : Person { public Employee Boss{get;set;}    }

答案 3 :(得分:-3)

Person不是Employee

Func<Employee, xxx>Func<Person, xxx>

之间无法投射