.NET supports covariance in interfaces, delegates, generic types and arrays. The interface or type has to specify it's covariant though with the out
keyword.
You can write
IEnumerable<Animal> animals=new List<Flea>();
or
var dict=new Dictionary<int,Flea>{
[1]=new Flea()
};
IEnumerable<Animal> animals=dict.Values;
This works because Dictionary.Values
returns an IEnumerable<Flea>
and IEnumerable is covariant - its definition is IEnumerable<out T>
.
KeyValuePair though isn't covariant which means that the classes that use it like IDictionary<TKey,TValue>
and IReadOnlyDictionary<TKey,TValue>
aren't either. This was intentional.
Since you only need to read from that dictionary, you can create an accessor method using a delegate or, in C# 7 and later, a local function. You can pass that function to methods that expect a Func<TKey,TValue>
and use it to read values from the dictionary.
If you have a method that needs key-based access, let's say :
void Process(Func<int,Animal> reader)
{
var value=reader(1);
}
In C# 7 you can write :
var dict =...
Animal get(int key)=>dict[key];
Process(get);
This cheats a bit, by using variable capture to access the dictionary.
Before C# 7 you'd use a delegate :
Func<int,Animal> get= key=>dict[key];
Process(get);
This may seem strange, but that's how LINQ itself works, by using predicates and delegates instead of interfaces and wrappers.