Juan Pablo Gomez
Juan Pablo Gomez

Reputation: 5534

Using Interface as parameter of List<T>

I have a class that may accept a List<IMyInterface> as parameter in one constructor

public class MyClass 
{
    public MyClass(List<IMyInterface> elements)
    {
    }
}  

And have an EF entity generated as this

public partial class MyEntity
{
    public string id {get;set;}
    . . . 
}

And an extension for this class that implements IMyInterfase (Bool MyEntity and its extension are on the same namespace)

public partial class MyEntity : IMyInterfase 
{
    public bool MyInterfaseImplementation {get;set;}
    .  .  .
} 

And at my view model constructor

var x = from a in db.MyEntity
        select a;

If I try to use a.ToList() as parameter for my class it throw InValid Arguments error

I was expecting this: If MyEntity implements IMyInterfase, then MyClass must accept it as parameter.

Am I wrong with this approach? What is the correct way to do this?

Upvotes: 1

Views: 189

Answers (3)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61982

Given that IEnumerable<out T> is covariant in T, you should be able to just do:

(from a in db.MyEntity
    select a).ToList<IMyInterface>()

Note that List<T> itself is not covariant (no "out" modifier on T).


Another solution is to change the parameter in the constructor to something that is covariant, like IReadOnlyList<out T>, as in:

public MyClass(IReadOnlyList<IMyInterface> elements)

You only need one of these two solutions, of course.

Upvotes: 1

Adi Lester
Adi Lester

Reputation: 25211

The reason why you're having this problem is that List<MyEntity> is not the same thing as List<IMyInterface>. The easiest thing to do would be to cast every object in the list to IIMyInterface:

var x = from a in db.MyEntity
        select a as IMyInterface;

This way x.ToList() will return List<IMyInterface> instead of List<MyEntity> and you will be able to pass it to MyClass's constructor.

EDIT:

As @Gert mentioned in the comments, you will need to modify your query as follows:

var x = (from a in db.MyEntity select a).AsEnumerable()
                                        .Cast<IMyInterface>()
                                        .ToList();

Upvotes: 1

Wiktor Zychla
Wiktor Zychla

Reputation: 48279

 var x = (from a in db.MyEntity
    select a).ToList();

 var c = new MyClass( x );

If it still doesn't work, try:

 var x = (from a in db.MyEntity
    select a).OfType<IMyInterface>().ToList();

I am not sure if List<T> is covariant.

Upvotes: 0

Related Questions