出于显而易见的原因,在适用的情况下,我一直首选使用IEnumerable而不是List。在当前项目中,我碰到了IList,在接受了它之后,Internet告诉我,除了一个属性(对进一步过滤的支持)之外,它们之间没有显着差异。

由于我不确定这对于C#中的迭代器意味着什么,因此我也同意这一点。在“支持进一步过滤”的点击数不胜数的点击中,任何可能的相关答案都淹没了,告诉我IEnumerable做到了,而IList却没有。

所以我在这里问两个问题。

  • 支持进一步过滤是什么意思?
  • 我如何用谷歌搜索这样的术语(从更一般的意义上来说)?

  • 由于这是基于许多帖子的一般性观察,因此我无法在此处列出所有内容。一个示例可能是this particular link

    最佳答案

    没有“进一步过滤”之类的东西。

    过滤集合通常是使用 IEnumerable.Where 扩展方法完成的,该方法是为IEnumerable接口(interface)定义的。由于IList继承自IEnumerable,因此您可以在两个接口(interface)上调用Where(在Where上调用IList实际上会调用 IEnumerable.Where 扩展方法)。因此,在两种情况下,都将调用相同的基本方法,并且结果值的类型将为IEnumerable(当应用于列表时不是IList)。这可能是造成混淆的原因(“您不能再过滤IList了,因为您已经没有了?”),但是没有什么能阻止您再次过滤生成的IEnumerable<T>,甚至不能编写自己的扩展方法来创建新的List。每次调用IEnumerable

    问题中链接到的帖子质量低下,不应该被信任。

    有关详细说明,请参见下文。

    尽管两种情况下通常都使用IList扩展方法(即LINQ),但是您可以从两个接口(interface)中过滤元素几乎相同,因为IEnumerable继承自Where。在两种情况下,您都可以随意链接许多Where语句:

    // `items` is an `IEnumerable<T>`, so we can call the `Where` extension method.
    // Each call creates a new instance, and keeps the previous one unmodified.
    IEnumerable<T> items = GetEnumerableItems();
    var filteredItems = items
        .Where(i => i.Name == "Jane")      // returns a new IEnumerable<T>
        .Where(i => i.Gender == "Female")  // returns a new IEnumerable<T>
        .Where(i => i.Age == 30)           // returns a new IEnumerable<T>
    
    // `list` is an `IList<T>`, which also inherits from `IEnumerable<T>`.
    // Calling `Where` on a list will also not modify the original list.
    IList<T> list = GetEnumerableItems();
    var filteredList = list
        .Where(i => i.Name == "John")      // returns a new IEnumerable<T>
        .Where(i => i.Gender == "Male")    // returns a new IEnumerable<T>
        .Where(i => i.Age == 30)           // returns a new IEnumerable<T>
        .ToList();                         // returns a new List<T> (optional)
    

    对该词进行谷歌搜索会返回几篇提及该词的文章(例如thisthis),它们似乎都在复制相同的来源,似乎是窃,没有背后的实际理由。我唯一想到的是,将 IEnumerable<T> 应用于IEnumerable<T>会返回一个新的(过滤后的)Where,您可以再次对其应用Where(“进一步”过滤)。但这确实很模糊,因为即使将生成的接口(interface)是IList<T>,将IEnumerable<T>应用于List<T>也不会阻止您对其进行过滤。如评论中所述,值得一提的是,IList<T>类作为FindAll的具体实现,公开了 List<T> 方法,该方法返回新的过滤后的具体IList<T>(并且可以“进一步过滤”),但这不是IEnumerable<T>的一部分。

    重复过滤FindAll和将列表过滤到新列表(例如,使用List<T>)之间的主要区别在于,后者需要在每个步骤中创建一个新的IEnumerable<T>实例,而Where使用延迟执行并且不会占用额外的内存从为每个Where调用存储一些微小的状态信息。再说一次,只是为了避免造成混淆,如果您在List<T>上调用IEnumerable<T>,您仍然可以获得IList懒惰的好处。

    实际差异:

    IList<T> (或实际上是O(1),我想您要指的是)表示可以由单独访问的对象的集合。这意味着您可以有效地(在List<T>时间内)获取某个位置的对象值以及列表的长度。 “不好的事情”是(假设它是在幕后实现的IEnumerable),这意味着您需要将整个集合保存在内存中。

    IEnumerable<T> (即其通用对应的IEnumerable)可以做的“唯一的事情”是迭代(零个或多个)项目。它没有索引的概念(在没有实际迭代或跳过该项目之前的所有项目的情况下,您无法“跳转”到索引)。而且,在通常情况下,如果没有每次都实际计数项目,您也无法有效地获得长度。另一方面,ojit_code是延迟求值的,这意味着它的元素在即将被求值之前不必存在于内存中。它可以在下面循环访问从磁盘中获取的数十亿行数据,并将其包装在数据库表的下面。它甚至可以是一个无限的集合。

    关于c# - 迭代器的 "further filtering"是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25302798/

    10-15 09:21