C#:foreach中的yield返回失败 – body不能是一个迭代器块
考虑这一点混淆的代码。 其目的是通过匿名构造函数即时创build一个新对象,并yield return
它。 目标是避免维护一个本地集合只是为了简单地return
它。
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 }; } }
不幸的是,这段代码产生了一个exception:
错误28“Foo.BuildComputerAssets()”的主体不能是迭代器块,因为“System.Collections.Generic.List”不是迭代器接口types
问题
- 这个错误信息是什么意思?
- 我怎样才能避免这个错误,并正确使用
yield return
?
您只能在返回IEnumerable
或IEnumerator
而不是List<T>
的函数中使用yield return
。
你需要改变你的函数返回一个IEnumerable<DesktopComputer>
。
或者,您可以重写该函数以使用List<T>.ConvertAll
:
return GetComputerIdTags().ConvertAll(pcTag => new DesktopComputer() { AssetTag = pcTag, Description = "PC " + pcTag, AcquireDate = DateTime.Now });
你的方法签名是错误的。 它应该是:
public static IEnumerable<DesktopComputer> BuildComputerAssets()
yield只能用于Iteratortypes:
yield语句只能出现在迭代器块中
迭代器被定义为
迭代器的返回types必须是IEnumerable,IEnumerator,IEnumerable <T>或IEnumerator <T>。
IList和IList <T>确实实现了IEnumerable / IEnumerable <T>,但是每个枚举器的调用者都需要上述四种types之一。
您还可以使用LINQ查询(在C#3.0 +中)实现相同的function。 这比使用ConvertAll
方法效率更低,但是更一般。 稍后,您可能还需要使用其他LINQfunction,如过滤:
return (from pcTag in GetComputerIdTags() select new DesktopComputer() { AssetTag = pcTag, Description = "PC " + pcTag, AcquireDate = DateTime.Now }).ToList();
ToList
方法将IEnumerable<T>
的结果转换为List<T>
。 我个人不喜欢ConvertAll
,因为它和LINQ一样。 但是因为它是早些时候添加的,所以不能用于LINQ(它应该被称为Select
)。