Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多参数Func方差_C#_Covariance_Func - Fatal编程技术网

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;}    }