private static void TestStructInterface()
{
IFoo foo1 = new FooClass(); // works
IFoo foo2 = new FooStruct(); // works
IEnumerable<IFoo> foos1 = new List<FooClass>(); // works
IEnumerable<IFoo> foos2 = new List<FooStruct>(); // compiler error
}
interface IFoo
{
string Thing { get; set; }
}
class FooClass : IFoo
{
public string Thing { get; set; }
}
struct FooStruct : IFoo
{
public string Thing { get; set; }
}
The compiler complains:
Cannot implicitly convert type 'System.Collections.Generic.List<Tests.Program.FooStruct>' to 'System.Collections.Generic.IEnumerable<Tests.Program.IFoo>'. An explicit conversion exists (are you missing a cast?)
Why?
Why is there a difference between classes and structs?
Any workarounds?
This has been already answered here - Why covariance and contravariance do not support value type , but summarizing it for easier look up.
The behavior you are trying to implement is called Variance.
This is due to a restriction enforced in CLR which is explained in Eric Lippert's Blog -
Covariant and Contravariant conversions of interface and delegate types require that all varying type arguments be of reference types
The reason is explained in MSDN:
Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.
Just like Bharathram Attiyannan answered, variance is simply not supported for value types.
The workaround is simple:
List<FooStruct> listOfFooStruct = new List<FooStruct>();
IEnumerable<IFoo> enumerableOfFoo = listOfFooStruct.Cast<IFoo>();
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