我有一个接口(IAnimal
),由两个类Bear和Goat实现。
在运行时,我可能会得到一个熊或山羊列表,但无论它们是什么,都需要分配给属性IEnumerable<IAnimal>
这是有效的,因为IEnumerable
是共变体。
但是,我现在需要从IEnumerable<IAnimal>
删除项目,这当然不起作用。
我需要做些什么才能删除项目?
以下是工作样本:
interface IAnimal {}
public class Bear : IAnimal {}
public class Goat : IAnimal {}
class Program
{
public static IEnumerable<IAnimal> CouldBeBearsOrGoats { get; set; }
static void Main(string[] args) {
var list = new List<int>() {1, 2, 3};
var bears = from l in list select new Bear();
var goats = from l in list select new Goat();
CouldBeBearsOrGoats = bears;
CouldBeBearsOrGoats = goats;
//How do I now remove an item?
}
}
如果我将CouldBeBearsOrGoats更改为List,那么我可以删除项目,但我不能再指定任何一种类型。
public static List<IAnimal> CouldBeBearsOrGoats { get; set; }
列表将会很长,所以我不想只是复制一份列表并使用副本。我正在做的是处理列表中的每个项目,然后将其删除,直到列表为空。
答案 0 :(得分:5)
由于您的源数据无论如何都是IEnumerable,您必须将其转换为List才能添加/删除元素。
List<IAnimal> ListOfAnimals1 = bears.Cast<IAnimal>().ToList();
List<IAnimal> ListOfAnimals2 = goats.Cast<IAnimal>().ToList();
答案 1 :(得分:2)
可能性是在LINQ查询中添加Cast
调用,以便将IEnumerable<Goat>
转换为IEnumerable<IAnimal>
(实际上创建了一个新的迭代器,每个元素都被转换)。
var bears = (from l in list select new Bear()).Cast<IAnimal>().ToList();
var goats = (from l in list select new Goat()).Cast<IAnimal>().ToList();
现在,bears
和goats
都是IAnimal
的可用数据,您可以对它们进行操作。
答案 2 :(得分:0)
我不认为只使用强类型集合 1 就可以轻松实现这一点,因为没有协变集合接口可以公开Remove
方法...
我看到了两种可能的解决方案:
使用由ICollection
实现的非通用List<T>
接口:
var collection = (ICollection) CouldBeBearsOrGoats;
collection.Remove(whatever);
缺点是实现ICollection<T>
的集合可能无法实现ICollection
...
使用动态:
dynamic collection = CouldBeBearsOrGoats
collection.Remove(whatever);
但它可能比之前的方法慢。
1 假设您不想通过将项目转换为IAnimal