dev*_*xer 13 c# ienumerable yield
通过一个教程(Professional ASP.NET MVC - Nerd Dinner),我遇到了这段代码:
public IEnumerable<RuleViolation> GetRuleViolations() {
if (String.IsNullOrEmpty(Title))
yield return new RuleViolation("Title required", "Title");
if (String.IsNullOrEmpty(Description))
yield return new RuleViolation("Description required","Description");
if (String.IsNullOrEmpty(HostedBy))
yield return new RuleViolation("HostedBy required", "HostedBy");
if (String.IsNullOrEmpty(Address))
yield return new RuleViolation("Address required", "Address");
if (String.IsNullOrEmpty(Country))
yield return new RuleViolation("Country required", "Country");
if (String.IsNullOrEmpty(ContactPhone))
yield return new RuleViolation("Phone# required", "ContactPhone");
if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
yield return new RuleViolation("Phone# does not match country", "ContactPhone");
yield break;
}
Run Code Online (Sandbox Code Playgroud)
我已经读过了yield,但我想我的理解仍然有点朦胧.它似乎做的是创建一个对象,允许循环遍历集合中的项目而不实际进行循环,除非并且直到它是绝对必要的.
不过,这个例子对我来说有点奇怪.我认为它正在做的是延迟任何RuleViolation实例的创建,直到程序员使用或者for eachLINQ扩展方法实际请求集合中的特定项.ElementAt(2).
不过,除此之外,我还有一些问题:
什么时候对if语句的条件部分进行评估?何时GetRuleViolations()调用或实际迭代枚举?换句话说,如果该值Title的变化来自null于Really Geeky Dinner我打电话的时间之间GetRuleViolations(),我试图其实遍历它的时候,会RuleViolation("Title required", "Title")创建或不?
为什么有yield break;必要?它到底在做什么?
假设Title为null或为空.如果我调用GetRuleViolations()然后连续两次迭代结果可枚举,将new RuleViolation("Title required", "Title")调用多少次?
Avi*_* P. 17
包含yield命令的函数与普通函数的处理方式不同.调用该函数时幕后发生的事情是,匿名类型是由函数的特定IEnumerable类型构成的,该函数创建该类型的对象并返回它.匿名类包含执行函数体的逻辑,直到yield每次IEnumerable.MoveNext调用时都执行下一个命令.这有点误导,函数的主体不像普通函数那样在一个批处理中执行,而是分段执行,每个部分在枚举器向前移动一步时执行.
关于你的问题:
if当你迭代到下一个元素时,每个都会被执行.yield break在上面的例子中确实没有必要.它的作用是终止枚举.1)举一个更简单的例子:
public void Enumerate()
{
foreach (var item in EnumerateItems())
{
Console.WriteLine(item);
}
}
public IEnumerable<string> EnumerateItems()
{
yield return "item1";
yield return "item2";
yield break;
}
Run Code Online (Sandbox Code Playgroud)
每次MoveNext()从IEnumerator代码调用时,从该yield点返回并移动到下一个可执行代码行.
2)yield break;将告诉IEnumerator我们没有更多要枚举的内容.
3)每次枚举一次.
运用 yield break;
public IEnumerable<string> EnumerateUntilEmpty()
{
foreach (var name in nameList)
{
if (String.IsNullOrEmpty(name)) yield break;
yield return name;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3429 次 |
| 最近记录: |