C#:foreach 中的yield return 失败 - 主体不能是迭代器块
考虑一下这段混淆的代码。目的是通过匿名构造函数动态创建一个新对象并yield 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
};
}
}
不幸的是,这段代码产生了一个异常:
错误 28 “Foo.BuildComputerAssets()”的主体不能是迭代器块,因为“System.Collections.Generic.List”不是迭代器接口类型
问题
- 此错误消息是什么意思?
- 如何避免此错误并正确使用
yield return
?
Consider this bit of obfuscated code. The intention is to create a new object on the fly via the anonymous constructor and yield return
it. The goal is to avoid having to maintain a local collection just to simply return
it.
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
};
}
}
Unfortunately, this bit of code produces an exception:
Error 28 The body of 'Foo.BuildComputerAssets()' cannot be an iterator block because 'System.Collections.Generic.List' is not an iterator interface type
Questions
- What does this error message mean?
- How can I avoid this error and use
yield return
properly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您只能在返回
IEnumerable
或IEnumerator
而不是List
的函数中使用yield return
>。您需要更改函数以返回
IEnumerable
。或者,您可以重写该函数以使用
List.ConvertAll< /代码>
:
You can only use
yield return
in a function that returns anIEnumerable
or anIEnumerator
, not aList<T>
.You need to change your function to return an
IEnumerable<DesktopComputer>
.Alternatively, you can rewrite the function to use
List<T>.ConvertAll
:您的方法签名错误。应该是:
Your method signature is wrong. It should be:
yield 仅适用于迭代器类型:
迭代器 定义为
IList 和 IList确实实现了 IEnumerable/IEnumerable,但是枚举器的每个调用者都期望上述四种类型之一,而不是其他类型。
yield only works on Iterator types:
Iterators are defined as
IList and IList<T> do implement IEnumerable/IEnumerable<T>, but every caller to an enumerator expects one of the four types above and none else.
您还可以使用 LINQ 查询(在 C# 3.0+ 中)实现相同的功能。这比使用
ConvertAll
方法效率低,但更通用。稍后,您可能还需要使用其他 LINQ 功能,例如过滤:ToList
方法将结果从IEnumerable
转换为List
代码>.我个人不喜欢ConvertAll
,因为它与 LINQ 做同样的事情。但因为它是较早添加的,所以它不能与 LINQ 一起使用(它应该被称为Select
)。You could also implement the same functionality using a LINQ query (in C# 3.0+). This is less efficient than using
ConvertAll
method, but it is more general. Later, you may also need to use other LINQ features such as filtering:The
ToList
method converts the result fromIEnumerable<T>
toList<T>
. I personally don't likeConvertAll
, because it does the same thing as LINQ. But because it was added earlier, it cannot be used with LINQ (it should have been calledSelect
).