我在学习一个教程(专业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;
}
我已经研究了yield
,但我觉得我的理解还有点模糊。它似乎创造了一个对象,允许在不实际执行循环的情况下循环遍历集合中的项目,除非绝对必要。
然而,这个例子对我来说有些奇怪。我认为它所做的是推迟创建任何RuleViolation
实例,直到程序员使用foreach
或类似于.ElementAt(2)
的LINQ扩展方法请求特定项的集合。
除此之外,我有一些问题:
当条件语句的部分被评估时?当调用
GetRuleViolations()
或当枚举实际迭代时?换句话说,如果在我调用GetRuleViolations()
和我尝试实际迭代之间,Title
的值从null
更改为Really Geeky Dinner
,那么是否会创建RuleViolation("Title required", "Title")
?yield break;
为什么是必需的?它在这里真正做了什么?假设
Title
为空或为null。如果我调用GetRuleViolations()
然后连续两次迭代生成的可枚举对象,new RuleViolation("Title required", "Title")
会被调用多少次?