Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
466 views
in Technique[技术] by (71.8m points)

c# - IDictionary<,> contravariance?

I have the following method in an external class

public static void DoStuffWithAnimals(IDictionary<string, Animal> animals)

In my calling code, I already have a Dictionary<string, Lion> object, but I can't pass this in as this method's argument. So a IDictionary<,> isn't contravariant? I can't see any reason why this shouldn't work.

The only solution I can think of is:

var animals = new Dictionary<string, Animal>();

foreach(var kvp in lions) {
    animals.Add(kvp.Key, kvp.Value);
}

Is there no way to pass this dictionary into this method, without having to create a new dictionary of the same objects?


EDIT:

As it's my method, I know that the only member I'm using from the dictionary is the getter of TValue this[TKey key], which is a member of IDictionary<TKey, TValue>, so in this scenario, I'm unable to use a 'wider' type for the parameter.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Firstly, covariance and contravariance in C# only apply to interfaces and delegates.

So your question is really about IDictionary<TKey,TValue>.

With that out of the way, it's simplest to just remember that an interface can only be co/contra-variant if all values of a type parameter are either only passed in, or only passed out.

For example (contravariance):

interface IReceiver<in T> // note 'in' modifier
{
    void Add(T item);
    void Remove(T item);
}

And (covariance):

interface IGiver<out T> // note 'out' modifier
{
    T Get(int index);
    T RemoveAt(int index);
}

In the case of IDictionary<TKey,TValue>, both type parameters are used in both an in and out capacity, meaning that the interface cannot be covariant or contravariant. It is invariant.

However, the class Dictionary<TKey,TValue> does implement IEnumerable<T> which is covariant.

A great reference for this is:

https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...