[英]Func variance with multiple parameters
在我們的代碼中嘗試了類似的東西,但它失敗了:
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>
。 存在顯式轉換(您是否錯過了演員?)
知道為什么嗎?
如果你看一下Func<T, TResult>
的簽名,你會看到輸入參數(在這種情況下為T
)是逆變的 ,返回類型( TResult
)是協變的
public delegate TResult Func<in T, out TResult>(T arg);
逆變量基本上是關於能夠將“更大”類型傳遞給期望“更小”類型的方法,其中協方差恰恰相反。
埃里克·利珀特( Eric Lippert )非常優雅(強調我的) :
如果具有引用類型參數的構造保留賦值兼容性的方向,則泛型類型I是協變的 (在T中)。 如果它顛倒了賦值兼容性的方向,則它是逆變的 (在T中)。 如果兩者都沒有 ,那就是不變的 。 通過這種方式,我們只是簡單地說,采用T並產生I的投影是協變/逆變/不變投影。
因為Func<T, TResult>
被定義為
public delegate TResult Func<in T, out TResult>(T arg);
正如你所看到的,第二個參數( TResult
)確實是一個協變,但第一個參數( T
,它是函數的輸入)實際上是一個逆變(你只能用不太衍生的東西來提供它)。
Func<Employee, Person>
很好,因為它與簽名匹配,而Func<Person, Person>
失敗,因為它不是。
請參閱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;} }
一個Person
不是Employee
Func<Employee, xxx>
和Func<Person, xxx>
之間沒有可能的Func<Employee, xxx>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.