使用Interface作为List<;T>;

本文关键字:gt Interface lt List 使用 作为 | 更新日期: 2024-09-25 20:51:03

我有一个类可以接受List<IMyInterface>作为一个构造函数中的参数

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

并将EF实体生成为该

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

以及实现IMyInterfase的这个类的扩展(Bool MyEntity和它的扩展在同一个命名空间上)

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

在我看来,模型构造函数

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

如果我尝试使用a.ToList()作为类的参数,它会抛出InValid Arguments错误

我本以为:如果MyEntity实现IMyInterfase,那么MyClass必须接受它作为参数。

这种做法我错了吗?正确的方法是什么?

使用Interface作为List<;T>;

出现此问题的原因是List<MyEntity>List<IMyInterface>不同。最简单的方法是将列表中的每个对象强制转换为IIMyInterface:

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

通过这种方式,x.ToList()将返回List<IMyInterface>而不是List<MyEntity>,并且您将能够将其传递给MyClass的构造函数。

编辑:

正如@Gert在评论中提到的,您需要修改您的查询如下:

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

假设IEnumerable<out T>T中的协变,您应该能够执行:

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

注意,List<T>本身是而不是协变(T上没有"out"修饰符)。


另一种解决方案是将构造函数中的参数更改为协变的参数,如IReadOnlyList<out T>,如下所示:

public MyClass(IReadOnlyList<IMyInterface> elements)

当然,您只需要这两个解决方案中的一个

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

如果仍然不起作用,请尝试:

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

我不确定List<T>是否是协变的。