I'm learning C# generics and making some dummy code for testing purposes. So, I'm testing the in Generic Modifier, which specifies that the type parameter is contravariant.
Given the below interface:
public interface IInterfaceTest<in T>
{
void Method(T value);
void Method(IList<T> values);
void Method(IEnumerable<T> values);
}
When compiling, I'm getting the error message:
[CS1961] Invalid variance: The type parameter 'T' must be invariantly valid on 'IInterfaceTest.Method(IList)'. 'T' is contravariant.
The error is related only with the line void Method(IEnumerable<T> values)
. If this line is removed, all works fine.
So my question is: Why can I use the generic contravariant with IEnumerable
but does not with IList
? Am I forgot something?
Thanks.
The question why it's not allowed for IList<T>
has been answered in the comments and linked questions already: IList<T>
is invariant in T
and so a contra-variant T
cannot be used here whatsoever.
What puzzled me at first is the fact that Method(IEnumerable<T>)
is allowed here. The strange thing is that variance is "turned around" when you use the T
as a type argument for another generic type.
Imagine this.
public interface ITestInterface<in T>
{
void Method(IEnumerable<T> e);
IEnumerable<T> GetMethod(); // illegal
}
public class Animal {}
public class Lion : Animal [}
public class Gnu : Animal {}
ITestInterface<Animal> animals;
ITestInterface<Lion> lions;
ITestInterface<Gnu> gnus;
Now the contra-variance of ITestInterface<in T>
in T
tells us that you can do
lions = animals;
And when you call lions.Method(e)
, you can only provide an IEnumerable<Lion>
. So the code of Method
can only enumerate Lion
s, which are all Animals
as animals.Method()
expects. Everything is fine.
On the other hand, the IEnumerable<T> GetMethod()
is illegal, because:
gnus = animals;
is legal, and now gnu.GetMethod()
would return an IEnumerable<Animal>
where you'd expect an IEnumerable<Gnu>
. And when you iterated, suprising animals could wait in that sequence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With