C# 多参数Func方差
尝试在我们的代码中添加类似的内容,但失败:C# 多参数Func方差,c#,covariance,func,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<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 { }
Func\u myFunc;
void Main()
{
Func test1=\u myFunc;//确定
Func test2=\u myFunc;//确定
Func test3=\u myFunc;//失败
Func test4=\u myFunc;//失败
}
公共类人士{}
公共类雇员:个人{}
最后两个案例给出了此错误:
无法将类型System.Func
隐式转换为System.Func
。存在显式转换(是否缺少强制转换?)
知道为什么吗?一个
人
不是员工
Func
和Func
之间不可能进行强制转换。如果查看Func
的签名,您将看到输入参数(T
在本例中)是反变的,返回类型(TResult
)是协变的
public委托TResult Func(T参数);
逆变基本上是指能够将“较大”类型传递给期望“较小”类型的方法,其中协方差正好相反
Eric Lippert说:
如果使用引用构造,则泛型I是协变的
类型参数保留赋值兼容性的方向。信息技术
如果反转赋值方向,则为逆变型(在T中)
兼容性。如果两者都不,则它是不变的。这样,我们
简单地说,用一种简洁的方式,表示
产生I是协变/逆变/不变投影
因为Func
是一个定义为
public delegate TResult Func<in T, out TResult>(T arg);
public委托TResult Func(T参数);
如您所见,第二个参数(TResult
)确实是协变的,但第一个参数(T
,它是函数的输入)实际上是一个逆变的(您只能向它提供派生较少的内容)
Func
可以,因为它与签名匹配;而Func
失败,因为它与签名不匹配
看好的,我想我现在明白了:
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;} }
void Main()
{
Func getEmployeesBoss=(Employee-Employee)=>{return Employee.Boss;};
//这是因为它期望一个人被返回并成为一名员工。老板就是一个人。
Func getEmployeesBoss1=getEmployeesBoss;
//这失败了,因为我可以将一个非员工的人传递给该func,而该func将不起作用。
Func getEmployeesBoss2=getEmployeesBoss;
}
类人{}
类Employee:Person{public Employee Boss{get;set;}
因为返回类型(Func的最后一个泛型参数)是协变的,而输入参数(Func的所有其他泛型参数)是逆变的。有趣的事实:方法组到委托的转换也是协变和逆变的。如果您有长颈鹿M(动物a)
和代表动物D(老虎t)
则D D=M代码>在C#中是合法的,尽管D甚至不是通用的。Lippert的原始帖子中有一个拼写错误。协变的应该是out T
。@haim770我认为埃里克不是这个意思。我假设他的意思是泛型类型I
在T中是协变/逆变的,这意味着每个T
。是的。我读了整篇文章,现在我明白了他的意思。谢谢这就是我的意思,但我同意我写的方式很混乱!遗憾的是,我不再有写msdn博客的权限。
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;} }