使用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
必须接受它作为参数。
这种做法我错了吗?正确的方法是什么?
出现此问题的原因是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>
是否是协变的。