如何分配列表<;熊>;或者List<;山羊>;到列表<;IAnimal>;

本文关键字:gt lt 列表 List 或者 山羊 IAnimal 何分配 分配 | 更新日期: 2023-09-27 18:25:20

我有一个接口(IAnimal),它由Bear和Goat两个类实现。

在运行时,我可能会得到一个Bears或Goats列表,但无论是哪一个,都需要将它们分配给属性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?

    }
}

如果我将CouldByearsOrGoats更改为List,那么我可以删除项目,但不能再分配任何一种类型。

public static List<IAnimal> CouldBeBearsOrGoats { get; set; } 

这个列表会很长,所以我不想只复制列表并使用副本。我正在做的是处理列表中的每个项目,然后将其删除,直到列表为空。

如何分配列表<;熊>;或者List<;山羊>;到列表<;IAnimal>;

由于源数据无论如何都是IEnumerable的,因此必须将其转换为List才能添加/删除元素。

    List<IAnimal> ListOfAnimals1 = bears.Cast<IAnimal>().ToList();
    List<IAnimal> ListOfAnimals2 = goats.Cast<IAnimal>().ToList();

一种可能性是在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();

现在bearsgoats都是IAnimal的可枚举项,您可以对它们进行操作。

我认为没有一种简单的方法可以只使用强类型集合来实现这一点1,因为没有公开Remove方法的协变集合接口。。。

我看到了两种可能的解决方案:

  • 使用由List<T>:实现的非通用ICollection接口

    var collection = (ICollection) CouldBeBearsOrGoats;
    collection.Remove(whatever);
    

    缺点是实现ICollection<T>的集合可能无法实现ICollection。。。

  • 使用动态:

    dynamic collection = CouldBeBearsOrGoats
    collection.Remove(whatever);
    

    但它可能比以前的方法慢。


1假设您不想通过将项强制转换为IAnimal来更改集合的实际类型