【问题标题】:How to make new IEnumerable collection and return it? [duplicate]如何制作新的 IEnumerable 集合并返回它? [复制]
【发布时间】:2021-05-02 11:09:42
【问题描述】:

我需要将一个IEnumerable 和一个委托传递给我的方法,然后对其进行过滤并返回一个带有通过过滤器的数字的IEnumerable 集合。

Func<int, bool> filter = x => x % 3 == 0;


public static IEnumerable<int> Filter(IEnumerable<int> numbers, Func<int, bool> filter)
{
    foreach (int number in numbers) 
    {
        if (filter.Invoke(number)) 
        {
            // add number to collection
        }
    }

    // return collection
}

我尝试过像这样创建一个新集合:

IEnumerable<int> result = new IEnumerable<int>();

但这是不可能的,因为IEnumerable 是一个抽象类。

我应该如何创建和返回这个集合?我知道有很多简单的方法可以做到这一点,但找不到任何方法。

【问题讨论】:

  • 这能回答你的问题吗? What is the yield keyword used for in C#?
  • 类似numbers.Where(filter)?您甚至可能不需要该方法,Enumerable.Where() 会为您完成(以及更多)。
  • 我需要一个方法,因为我的任务是这样说的。但就是这样,我知道有一种简单的方法可以做到这一点。谢谢。
  • 你不能实例化IEnumerable&lt;T&gt;,因为它是一个接口。如果您使用List&lt;T&gt;(实现IEnumerable&lt;T&gt;),您将能够向其中添加项目然后返回。
  • 但这是不可能的,因为 IEnumerable 是一个抽象类。 - 不,实际上 - IEnumerable 是一个接口 - 不是一个抽象类!

标签: c# delegates ienumerable


【解决方案1】:

正如@somebody 指出的那样,正确的做法是使用yield return

public static IEnumerable<int> Filter(IEnumerable<int> numbers, Func<int, bool> filter) {
    foreach (int number in numbers) {
        if (filter.Invoke(number)) {
            yield return number;
        }
    }
}

当您返回的集合(您返回的IEnumerable&lt;int&gt;)被枚举(通过foreach 或对ToList 之类的调用)时,将为第一个项目调用您的代码。当您到达yield return 时,将返回第一个数字。当第二次(和后续的)迭代发生时,代码将继续在yield return之后的行上执行。

就其价值而言,您的代码与 LINQ 的 Where 扩展方法对 IEnumerable&lt;T&gt; 所做的几乎完全相同

【讨论】:

  • 那么这里用什么更好呢?有什么区别吗?
  • 使用Where。您不需要编写或维护的代码要便宜得多(而且,考虑到它与框架一起提供,出现错误的可能性要小得多)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 2011-10-02
相关资源
最近更新 更多