【问题标题】:Why using yield return here?为什么在这里使用收益回报?
【发布时间】:2012-09-16 06:22:39
【问题描述】:

我在open source project 中找到了以下方法:

    static IEnumerable<T> Cat<T>(T t) {
        yield return t;
    }

据我所知,它除了返回一个包含tIEnumerable&lt;T&gt; 之外什么也没做。如果我是对的,它实际上相当于例如return new List&lt;T&gt;{t};,在这里使用yield return 的目的/优势是什么?如果我错了,我会错过什么?

Full source can be found here.

【问题讨论】:

  • 两者彼此接近,但 IEnumerable 与 List 不同,选择的方法是我能想到的最简单的方法来获取包含单个项目的集合在里面。

标签: c# yield yield-return


【解决方案1】:

这只会创建一个包含单个元素的可枚举类型 (t)。实际上,您是正确的 - 它实际上与仅返回带有一个元素的新 List&lt;T&gt; 或带有一个元素的新数组等非常相似。

主要区别在于返回的类型实际上不是List&lt;T&gt; 或数组——它将是编译器生成的类型。例如,您将无法将结果转换为列表并添加元素。实际上,它的行为与您描述的返回新的List&lt;T&gt; 相同。

除了开发人员可能更喜欢这种语法之外,可能没有真正的优势。我怀疑它可能被用来允许单个元素与 API 的其他部分一起工作,这些部分期望传入 IEnumerable&lt;T&gt;,尽管方法名称还有一些不足之处,IMO。

【讨论】:

  • +1 在考虑此类事情时,无法将其转换回List 可能是一个重要因素,同意(尽管在这种情况下肯定不是)。
【解决方案2】:

返回一个实际的集合和使用yield 的区别只是你返回的对象的类型。

如果您返回任何实现IEnumerable&lt;T&gt; 的集合,则返回的对象的实际类型将是该类型。例如,如果您返回 List&lt;T&gt;,则返回的引用将是 IEnumerable&lt;T&gt; 类型,但引用指向的对象的实际类型是 List&lt;T&gt; 的实例。

如果您使用yield,编译器将创建一个没有已知名称的枚举器对象。返回的引用类型也将是IEnumerable&lt;T&gt;,但引用指向的对象的实际类型将是编译器创建的。

例如获取为整数创建的枚举器类型的名称:

Console.WriteLine(Cat<int>(42).GetType().Name);

将显示编译器使用的内部名称,例如我从代码中得到的这个结果:

<Cat>d__5`1

如果函数将返回 List&lt;int&gt;,则类型将显示为:

List`1

让编译器为此创建枚举器的动机可能只是因为它比这样的东西短:

static IEnumerable<T> Cat<T>(T t) {
  List<T> list = new List<T>(1);
  list.Add(t);
  return list;
}

(您可以使用较新版本的 C# 中的快捷方式将其写得更短一些,但仍不如 yield 短。)

当类型为集合时,可以将引用强制转换为实际类型并更改集合中的值:

IEnumerable<int> ienum = Cat<int>(42);

((List<int>)ienum)[0] = 1337;

foreach (int value in ienum) {
  Console.WriteLine(value);
}

将输出:

1337

【讨论】:

    【解决方案3】:

    此函数将单个项目转换为可枚举 如果你有一个可枚举的,并且你想追加一个项目,例如:

     IEnumerable<someType> Columns;
    
     var headers = String.Join(",", Columns.Select(c => c.Name).Concat(new string[] { "Last Column" }));
    

    写的更好

     var headers = String.Join(",", Columns.Select(c => c.Name).Concat(Cat("Last Column")));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      • 2013-08-15
      • 2011-01-13
      • 2011-05-27
      • 2011-08-08
      • 2010-09-29
      相关资源
      最近更新 更多