C#:foreach fails中的yield-return-body不能是迭代器块

C#:foreach fails中的yield-return-body不能是迭代器块,c#,iterator,yield,C#,Iterator,Yield,考虑一下这段模糊的代码。其目的是通过匿名构造函数动态创建一个新对象,并返回它。这样做的目的是避免为了简单地返回它而维护本地集合 public static List<DesktopComputer> BuildComputerAssets() { List<string> idTags = GetComputerIdTags(); foreach (var pcTag in idTags) { yield r

考虑一下这段模糊的代码。其目的是通过匿名构造函数动态创建一个新对象,并
返回它。这样做的目的是避免为了简单地
返回它而维护本地集合

public static List<DesktopComputer> BuildComputerAssets()
{           
    List<string> idTags = GetComputerIdTags();

    foreach (var pcTag in idTags)
    {
        yield return new DesktopComputer() {AssetTag= pcTag
                                          , Description = "PC " + pcTag
                                          , AcquireDate = DateTime.Now
                                           };
    }            
}
公共静态列表BuildComputerAssets()
{           
List idTags=GetComputerIdTags();
foreach(idTags中的var pcTag)
{
返回新的桌面计算机(){AssetTag=pcTag
,Description=“PC”+pcTag
,AcquireDate=DateTime.Now
};
}            
}
不幸的是,这段代码产生了一个异常:

错误28“Foo.BuildComputerAssets()”的主体不能是迭代器块,因为“System.Collections.Generic.List”不是迭代器接口类型

问题

  • 这个错误消息是什么意思
  • 如何避免此错误并正确使用
    收益率返回

只能在返回
IEnumerable
IEnumerator
的函数中使用
产生返回
,而不能在
列表
中使用

您需要更改函数以返回
IEnumerable

或者,您可以重写函数以使用:


你的方法签名是错误的。应该是:

public static IEnumerable<DesktopComputer> BuildComputerAssets()
公共静态IEnumerable BuildComputerAssets()
仅适用于迭代器类型:

yield语句只能出现在迭代器块中

定义为

迭代器的返回类型必须是IEnumerable、IEnumerator、IEnumerable或IEnumerator


IList和IList确实实现了IEnumerable/IEnumerable,但是枚举器的每个调用方都需要上述四种类型中的一种,而不是其他类型。

您也可以使用LINQ查询(在C#3.0+中)实现相同的功能。这比使用
ConvertAll
方法效率低,但更通用。稍后,您可能还需要使用其他LINQ功能,例如过滤:

return (from pcTag in GetComputerIdTags()
        select new DesktopComputer() { 
          AssetTag    = pcTag, 
          Description = "PC " + pcTag, 
          AcquireDate = DateTime.Now 
        }).ToList();

ToList
方法将结果从
IEnumerable
转换为
List
。我个人不喜欢
ConvertAll
,因为它和LINQ做同样的事情。但是因为它是在前面添加的,所以不能与LINQ一起使用(它应该被称为
Select
)。

您能解释一下原因吗?@LampPost:because
yield return
创建了一个IEnumerator实现。
return (from pcTag in GetComputerIdTags()
        select new DesktopComputer() { 
          AssetTag    = pcTag, 
          Description = "PC " + pcTag, 
          AcquireDate = DateTime.Now 
        }).ToList();