我正在编写验证逻辑,我希望调用者只获得他们真正需要的验证消息的数量(有些情况下,只需要第一个验证消息,其他时候,我们现在想要的所有问题都是给定数据)
鉴于此,我想"很棒!我将返回一个IEnumerable,并使用yield返回每个结果。如果在枚举上使用了FirstOrDefault(),则只会执行第一次失败的验证,其中将跳过以下内容,除非我们在验证结果上调用ToList()可枚举。
我所看到的问题是,如果我想将我的验证逻辑分解为多个方法,每个方法都返回一个Enumerable,我必须枚举那个设置,同时还有另一个yield return。 (见下面的简化示例)
public IEnumerable<string> Validate(ClassToValidate obj)
{
if(string.IsNullOrEmpty(obj.Name)
{
yield return "empty name";
}
foreach(var message in ValidateSubObject(obj.OtherObjectToValidate))
{
yield return message;
}
}
private IEnumerable<string> ValidateSubObject(OtherClass objToValidate)
{
yield return ...
}
是否还有其他一些我缺少的关键字,我可以&#34;收益返回设置&#34;从另一个返回另一个相同数据类型的IEnumerable的方法? I.E.是否有比以下更简单的语法:
foreach(var message in ValidateSubObject(obj.OtherObjectToValidate))
{
yield return message;
}
答案 0 :(得分:3)
你不能yield return
多件物品。如果要使用迭代器方法来连接序列,则必须循环遍历它们。
当然,你总是可以完全放弃yield return
并构建你的IEnumerable<T>
以使用其他方法返回(LINQ&#39; Concat
方法立即浮现在脑海中。)< / p>
public IEnumerable<string> Validate(ClassToValidate obj)
{
var subObjectMessages = ValidateSubObject(obj.OtherObjectToValidate);
if (string.IsNullOrEmpty(obj.Name))
{
return new[] { "empty name" }.Concat(subObjectMessages);
}
return subObjectMessages;
}
答案 1 :(得分:2)
在功能中引入yield
后,您必须坚持使用它。目前常见的方法是使用LINQ,它通常更灵活。
public IEnumerable<string> Validate(ClassToValidate obj)
{
return (String.IsNullOrEmpty(obj.Name) ? new [] { "empty name" } : Enumerable.Empty<string>())
.Concat(ValidateSubObject(obj.OtherObjectToValidate));
}