LINQ之外的产量是否有用?

Bob*_*Bob 26 .net c# linq yield

当我认为我可以使用yield关键字时,我退后一步,看看它将如何影响我的项目.我总是最终返回一个集合而不是yeilding,因为我觉得保持yeilding方法状态的开销不会给我带来太大的影响.在几乎所有我返回集合的情况下,我觉得90%的时间,调用方法将迭代集合中的所有元素,或者将在整个集合中寻找一系列元素.

我确实理解它在linq中的用处,但我觉得只有linq团队正在编写这样复杂的可查询对象,这些对象的产生是有用的.

有没有人写过像linq这样的产品有用吗?

Jam*_*ran 27

请注意,对于yield,您将迭代集合一次,但是当您构建列表时,您将迭代它两次.

以一个过滤器迭代器为例:

IEnumerator<T>  Filter(this IEnumerator<T> coll, Func<T, bool> func)
{
     foreach(T t in coll)
        if (func(t))  yield return t;
}
Run Code Online (Sandbox Code Playgroud)

现在,你可以链接这个:

 MyColl.Filter(x=> x.id > 100).Filter(x => x.val < 200).Filter (etc)
Run Code Online (Sandbox Code Playgroud)

你的方法是创建(和折腾)三个列表.我的方法只迭代一次.

此外,当您返回集合时,您正在强制对您的用户进行特定实现.迭代器更通用.

  • 该过滤器基本上是LINQ Where扩展方法. (5认同)
  • :)我有一个VS2008项目,除了SO代码片段之外什么都没有...... (2认同)

Ori*_*rds 19

我确实理解它在linq中的用处,但我觉得只有linq团队正在编写这样复杂的可查询对象,这些对象的产生是有用的.

只要它在.NET 2.0中实现,产量就很有用,早在人们想到LINQ之前很久.

我为什么要写这个函数:

IList<string> LoadStuff() {
  var ret = new List<string>();
  foreach(var x in SomeExternalResource)
    ret.Add(x);
  return ret;
}
Run Code Online (Sandbox Code Playgroud)

当我可以使用yield时,无需充分理由就可以节省创建临时列表的工作量和复杂性:

IEnumerable<string> LoadStuff() {
  foreach(var x in SomeExternalResource)
    yield return x;
}
Run Code Online (Sandbox Code Playgroud)

它还具有巨大的性能优势.如果您的代码恰好使用集合的前5个元素,那么使用yield通常会避免加载超过该点的任何内容.如果您构建一个集合然后返回它,您将浪费大量的时间和空间来加载您永远不需要的东西.

我可以继续下去....


Mor*_*sen 12

我最近不得不以Expression类的形式表达数学表达式.在评估表达式时,我必须通过后序树行走来遍历树结构.为此,我实现了IEnumerable <T>,如下所示:

public IEnumerator<Expression<T>> GetEnumerator()
{
    if (IsLeaf)
    {
        yield return this;
    }
    else
    {
        foreach (Expression<T> expr in LeftExpression)
        {
            yield return expr;
        }
        foreach (Expression<T> expr in RightExpression)
        {
            yield return expr;
        }
        yield return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地使用foreach来遍历表达式.您还可以添加属性以根据需要更改遍历算法.

  • 如果你只是做foreach(x收集){yield return x;} ...你可以这样做.选择(x => x).如果你想对集合中的一组项目进行工作,你可以创建一个扩展方法.Foreach <T,TResult>(IEnumerable <T> col,Action <T,TResult> action) (3认同)

Jon*_*eet 11

在以前的公司,我发现自己写这样的循环:

for (DateTime date = schedule.StartDate; date <= schedule.EndDate; 
     date = date.AddDays(1))
Run Code Online (Sandbox Code Playgroud)

使用一个非常简单的迭代器块,我能够将其更改为:

foreach (DateTime date in schedule.DateRange)
Run Code Online (Sandbox Code Playgroud)

它使代码更容易阅读,IMO.

  • 哇 - Jon Skeet代码我不同意!= X从第一个例子可以看出,你在几天内迭代,但第二个例子中缺少清晰度.我会使用'schedule.DateRange.Days()'之类的东西来避免歧义. (2认同)
  • 挑剔是好的,分裂的头发是好的,对编码风格的评论和建议总是欢迎:) (2认同)

Kei*_*ith 8

yield 是为C#2开发的(在C#3中的Linq之前).

在处理数据访问和重复计算时,我们在大型企业C#2 Web应用程序中大量使用它.

只要你有多个元素可以多次击中,集合就很棒.

然而,在许多数据访问场景中,您有大量的元素,您不一定需要在一个伟大的大集合中传递.

这基本上就是它SqlDataReader所做的 - 它只是一个前向的自定义枚举器.

是什么yield让你做的是快速,用最少的代码编写自定义枚举.

一切yield都可以在C#1中完成 - 它只需要大量代码就可以完成.

Linq确实最大化了屈服行为的价值,但它肯定不是唯一的应用程序.