Set*_*o N 21 c# ienumerable return yield-return
为什么我们不能在同一方法中同时使用return和yield return?
例如,我们可以在下面使用GetIntegers1和GetIntegers2,但不能使用GetIntegers3.
public IEnumerable<int> GetIntegers1()
{
  return new[] { 4, 5, 6 };
}
public IEnumerable<int> GetIntegers2()
{
  yield return 1;
  yield return 2;
  yield return 3;
}
public IEnumerable<int> GetIntegers3()
{
  if ( someCondition )
  {
    return new[] {4, 5, 6}; // compiler error
  }
  else
  {
    yield return 1;
    yield return 2;
    yield return 3;
  }
}
Dar*_*rov 19
return很渴望.它立即返回整个结果集.yield return构建一个枚举器.在幕后,C#编译器在您使用时会为枚举器发出必要的类yield return.编译器不会查找运行时条件,例如if ( someCondition )在确定是否应该为可枚举的代码发出时,或者有一个返回简单数组的方法时.它检测到你的方法中你正在使用这两个是不可能的,因为他不能发出枚举器的代码,同时让方法返回一个普通数组,所有这些都用于相同的方法.
Mar*_*ell 11
不,你不能这样做 - 迭代器块(带有a的东西yield)不能使用常规(非收益)return.相反,您需要使用2种方法:
public IEnumerable<int> GetIntegers3()
{
  if ( someCondition )
  {
    return new[] {4, 5, 6}; // compiler error
  }
  else
  {
    return GetIntegers3Deferred();
  }
}
private IEnumerable<int> GetIntegers3Deferred()
{
    yield return 1;
    yield return 2;
    yield return 3;
}
或者因为在这种特定情况下,两者的代码已经存在于其他两种方法中:
public IEnumerable<int> GetIntegers3()
{
  return ( someCondition ) ? GetIntegers1() : GetIntegers2();
}
编译器使用yield语句(return或break)重写任何方法.它目前无法处理可能会或可能不会的方法yield.
我建议阅读Jon Skeet的深度C#的第6章,其中第6章是免费的 - 它非常好地涵盖了迭代器块.
我认为没有理由为什么在c#编译器的未来版本中这是不可能的.其他.Net语言确实以'yield from'运算符的形式支持类似的东西(参见参考资料F# yield!).如果这样的运算符存在于c#中,它将允许您以下列形式编写代码:
public IEnumerable<int> GetIntegers()
{
  if ( someCondition )
  {
    yield! return new[] {4, 5, 6};
  }
  else
  {
    yield return 1;
    yield return 2;
    yield return 3;
  }
}