【发布时间】:2010-12-30 13:46:18
【问题描述】:
通过教程(Professional ASP.NET MVC - Nerd Dinner),我发现了这个 sn-p 代码:
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;
}
我已经阅读了yield,但我想我的理解仍然有点模糊。它似乎要做的是创建一个对象,允许在集合中的项目之间循环而不实际执行循环,除非并且直到绝对必要为止。
不过,这个例子对我来说有点奇怪。我认为它所做的是延迟任何RuleViolation 实例的创建,直到程序员使用for each 或像.ElementAt(2) 这样的LINQ 扩展方法实际请求集合中的特定项目。
不过,除此之外,我还有一些问题:
if语句的条件部分何时得到评估?何时调用GetRuleViolations()或实际迭代可枚举?换句话说,如果Title的值在我调用GetRuleViolations()和我尝试实际迭代它的时间之间从null更改为Really Geeky Dinner,是否会创建RuleViolation("Title required", "Title")?为什么需要
yield break;?它到底在做什么?假设
Title为空或为空。如果我调用GetRuleViolations(),然后连续两次迭代生成的可枚举,new RuleViolation("Title required", "Title")将被调用多少次?
【问题讨论】:
-
.Net 编译器将这种语法糖变成了一种更加混蛋的形式。编译示例,然后将 IL 加载到反射器中。您应该能够准确地了解那里发生了什么。
标签: c# ienumerable yield