0

I was trying to build a covariant IEnumerable for dictionaries via

public interface ICovariantKeyValuePair<K, out V>
{
  K Key { get; }
  V Value { get; }
}

because I wanted to use only one method to process differently typed dictionaries with some common value type. In the end I was really surprised having overlooked the really simple solution with a generic method

public void Print<S,T>(Dictionary<S,T> dict) { ... }

Now I am wondering what the real benefit of covariant interfaces is and what one is able to do only with these and with no other means.

Edit I understand that it makes sense if I want to keep two values together like it is the case with my covariant Key-Value-Pair described above. The following example from Heinzi (see below)

var kv1 = new CovariantKeyValuePair<string, Dog>("MyDog", myDog);
var kv2 = new CovariantKeyValuePair<string, Cat>("MyCat", myCat);
ICovariantKeyValuePair<string, Animal>[] myAnimals = { kv1, kv2 };

clearly works only with covariant interfaces. But in order to get to the central point let's simplify it further: I can write

Dog d = new Dog();
Cat c = new Cat();
List<Animal> l = new List<Animal>() { d, c };

without the necessity of covariance in my data types.

So the benefit of covariant interface over List<BaseType> data structures and over methods alike Foo<BaseType>(..) is for "when needing to keep things together where some inner part has a inheritance relationship attached" like in the case of Key-Value-Pairs?

David
  • 2,426
  • 3
  • 24
  • 36
  • You should take a look at this post here: http://stackoverflow.com/questions/2719954/understanding-covariant-and-contravariant-interfaces-in-c-sharp – Daniel Hakimi Dec 08 '15 at 19:34
  • 1
    You might be getting downvotes because this question could be interpreted as being primarily opinion-based rather than being able to be answered with an objectively correct answer. "What can covariant interfaces provide that generic parameters cannot?" however, can be objectively answered. – Colin Young Dec 09 '15 at 14:11

1 Answers1

2

I think this is a very interesting question. You are basically asking for an example where (1) there is a simple solution using a covariant interface but (2) there is no simple solution if your only option is to make methods generic.

Here's an example: Let's say I want to have an array of key-value pairs, where the key is a string and the value is some subtype of animal. With your covariant type, I can do the following:

var kv1 = new CovariantKeyValuePair<string, Dog>("MyDog", myDog);
var kv2 = new CovariantKeyValuePair<string, Cat>("MyCat", myCat);

ICovariantKeyValuePair<string, Animal>[] myAnimals = { kv1, kv2 };

That's only possible because the type is covariant, i.e., because kv1 is a ICovariantKeyValuePair<string, Animal>.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • I extended my question based on your input to in order to hopefully get closer to the central point. I understand that what you wrote is not possible with dictionaries as long as I do not will to split up the key and the value into two separate arguments. – David Dec 09 '15 at 15:07