Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEnumerable<IMyInterface> Implicitly From Class[] But Not From Struct[]. Why?

Tags:

c#

Given:

public interface IMyInterface{

}

public class MyClass:IMyInterface{
     public MyClass(){}
}

public struct MyStruct:IMyInterface{
     private int _myField;

     public MyStruct(int myField){_myField = myField;}
}

Why can I write:

IEnumerable<IMyInterface> myClassImps = new[] {
    new MyClass(),
    new MyClass(),
    new MyClass()
};

But not:

IEnumerable<IMyInterface> myStructImps = new[]{
    new MyStruct(0),
    new MyStruct(1),
    new MyStruct(2)
};

Which gives me the following warning:

Error 29 Cannot implicitly convert type 'MyApp.MyNS.MyStruct[]' to 'System.Collections.Generic.IEnumerable<MyApp.MyNS.IMyInterface>'

And must instead be written:

IEnumerable<IMyInterface> myStructImps = new IMyInterface[]{
    new MyStruct(0),
    new MyStruct(1),
    new MyStruct(2)
};
like image 348
Grokodile Avatar asked Apr 28 '11 21:04

Grokodile


1 Answers

The issue is array covariance. This specification talk about it:

For any two reference-types A and B, if an implicit reference conversion (Section 6.1.4) or explicit reference conversion (Section 6.2.3) exists from A to B, then the same reference conversion also exists from the array type A[R] to the array type B[R], where R is any given rank-specifier (but the same for both array types)

A simpler example of this that also fails is

int[] c = new int[0];
object[] d = c;

while

string[] c = new string[0];
object[] d = c;

works fine. You are basically trying to do the same thing. You have an array of value types MyStruct and you are trying to implicitly cast it to IMyInterface, which is not covered by the array covariance specification.

like image 87
Yuriy Faktorovich Avatar answered Oct 13 '22 06:10

Yuriy Faktorovich