.NET 支持接口、委托、泛型类型和数组中的协变。接口或类型必须指定它的协变性out
关键词。
你可以写
IEnumerable<Animal> animals=new List<Flea>();
or
var dict=new Dictionary<int,Flea>{
[1]=new Flea()
};
IEnumerable<Animal> animals=dict.Values;
这有效是因为Dictionary.Values
返回一个IEnumerable<Flea>
and IE可枚举 https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=netframework-4.8是协变的 - 它的定义是IEnumerable<out T>
.
键值对 https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.keyvaluepair-2?view=netframework-4.8虽然不是协变的,这意味着使用它的类就像IDictionary<TKey,TValue>
and IReadOnlyDictionary<TKey,TValue>
也不是。这是故意的。
因为你只需要read从该字典中,您可以使用委托创建访问器方法,或者在 C# 7 及更高版本中使用本地函数创建访问器方法。您可以将该函数传递给期望的方法Func<TKey,TValue>
并用它从字典中读取值。
如果您有一种需要基于密钥的访问的方法,可以这样说:
void Process(Func<int,Animal> reader)
{
var value=reader(1);
}
在 C# 7 中你可以这样写:
var dict =...
Animal get(int key)=>dict[key];
Process(get);
通过使用变量捕获来访问字典,这有点作弊。
在 C# 7 之前,您可以使用委托:
Func<int,Animal> get= key=>dict[key];
Process(get);
这可能看起来很奇怪,但就是这样LINQ它本身是通过使用谓词和委托而不是接口和包装器来工作的。