为什么在这里使用收益率?

时间:2012-09-24 18:47:46

标签: c# yield yield-return

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

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

据我了解,它只会返回包含IEnumerable<T>的{​​{1}}。如果我是对的,那它就等同于t,在这里使用return new List<T>{t};的目的/优势是什么?如果我错了,我会错过什么?

Full source can be found here

3 个答案:

答案 0 :(得分:5)

这只是一个包含单个元素(t)的可枚举类型。实际上,你是对的 - 它实际上非常类似于只用一个元素返回一个新的List<T>,或者用一个元素返回一个新的数组等。

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

除了开发人员可能更喜欢这种语法之外,可能没有真正的优势。我怀疑可能用于允许单个元素与API的其他部分一起工作,期望传递IEnumerable<T>,尽管方法名称有点不尽如人意,IMO。

答案 1 :(得分:3)

返回实际集合和使用yield之间的区别只是您返回的对象的类型。

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

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

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

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

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

<Cat>d__5`1

如果该函数将返回List<int>,则该类型将显示为:

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

答案 2 :(得分:0)

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

 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")));