【问题标题】:Any benefit of using yield in this case?在这种情况下使用产量有什么好处?
【发布时间】:2017-09-08 22:10:17
【问题描述】:

我在工作中维护一些代码,原作者已经不在了,所以想在这里问一下,看看能不能满足我的好奇心。

下面是一些使用 yield 的代码(匿名)。据我所知,它并没有增加任何好处,只返回一个列表就足够了,也许也更具可读性(至少对我来说)。只是想知道我是否遗漏了什么,因为这种模式在代码库的几个地方重复。

public virtual IEnumerable<string> ValidProductTypes
{
  get
  {
    yield return ProductTypes.Type1;
    yield return ProductTypes.Type2;
    yield return ProductTypes.Type3;
  }
}

此属性用作某些类的参数,该类仅使用它来填充集合:

var productManager = new ProductManager(ValidProductTypes);

public ProductManager(IEnumerable<string> validProductTypes)
{
  var myFilteredList = GetFilteredTypes(validProductTypes);
}

public ObservableCollection<ValidType> GetFilteredTypes(IEnumerable<string> validProductTypes)
{
  var filteredList = validProductTypes
                    .Where(type => TypeIsValid); //TypeIsValid returns a ValidType
  return new ObservableCollection<ValidType>(filteredList);
}

【问题讨论】:

  • 一个好处可能是,虽然在这种情况下似乎不是这样,但当枚举未完成时,例如使用 FirstOrDefault,并非所有潜在的代价高昂的执行都会在以后执行产量,这将是一个列表。在这种情况下,如果 Type2 是重属性,但枚举不消耗它,它会比列表轻。
  • 恕我直言,这种情况最好用一个简单的数组来实现。我不觉得迭代器方法语法增加了任何东西。但这主要是一个意见问题。您似乎没有任何实际的、实用的编程问题要在这里解决。

标签: c# yield-return


【解决方案1】:

我想说返回IEnumerable&lt;T&gt; 并使用yield return 实现它是最简单的 选项。

如果你看到一个方法返回一个IEnumerable&lt;T&gt;,你真的只能用它做一件事:迭代它。对它的任何更复杂的操作(如使用 LINQ)只是封装了特定的迭代方式。

如果一个方法返回一个数组或列表,您还可以获得对其进行变异的能力,您可能会开始怀疑这是否是 API 的可接受用途。例如,如果您执行ValidProductTypes.Add("a new product"),会发生什么?

如果您只是在谈论实现,那么差异会变得更小。但是调用者仍然可以将返回的数组或列表从IEnumerable&lt;T&gt; 转换为其具体类型并对其进行变异。任何人实际上认为这是 API 的预期用途的可能性很小,但对于 yield return,可能性为零,因为这是不可能的。

考虑到我会说语法具有大致相同的复杂性和易于理解,我认为yield return 是一个合理的选择。尽管使用 C# 6.0 表达式主体属性,但数组的语法可能会占上风:

public virtual IEnumerable<string> ValidProductTypes =>
  new[] { ProductTypes.Type1, ProductTypes.Type2, ProductTypes.Type3 };

上面的答案是假设这不是性能关键代码,因此相当小的性能差异并不重要。如果这是性能关键代码,那么您应该衡量哪个选项更好。而且您可能还想考虑摆脱分配(可能通过在字段中缓存数组或类似的方式),这可能是主要因素。

【讨论】:

  • 虽然看起来很简单,但我希望那些yield return 的用法可以有效地将事物变成一个生成器,从而在引擎盖下产生比使用可枚举集合更复杂的 IL。我认为这也会对性能产生影响(不是关键,但可能与普通数组不同)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2013-04-01
  • 2016-12-29
  • 2015-01-30
  • 2013-04-23
相关资源
最近更新 更多