Ian*_*cer 1 c# ienumerable language-features
当处理一个包含none,一个或多个项的枚举时,foreach
循环可以很容易地迭代它们,LINQ Select
可以很容易地从枚举项目中项目.
foreach (var attr in p.GetCustomAttributes().OfType<A>()) ...
Run Code Online (Sandbox Code Playgroud)
当处理包含none或只有一个项目的枚举时,事情会有点棘手.您可以使用相同的foreach
循环,但不能确保只存在其中一个项目,并且它可能会执行多次.
您可以添加.Take(1)
以清楚地表明您只需要一个并确保循环仅执行一次.但如果不止一个,那就不会抛出异常.
foreach (var attr in ...().Take(1)) ...
Run Code Online (Sandbox Code Playgroud)
您可以事先添加一个检查,以确保只有一个,或者可能是一个新的代码合同来检查,但这是相当混乱的:
Contract.Requires(p..GetCustomAttributes().OfType<A>().Count() < 2);
foreach (var attr in p.GetCustomAttributes().OfType<A>()) ...
Run Code Online (Sandbox Code Playgroud)
您甚至可以创建一个新的扩展方法.ZeroOrOne<T>()
,它返回枚举中的第一个元素,然后如果您要求更多,则抛出异常.
foreach (var attr in ...().ZeroOrOne()) ...
Run Code Online (Sandbox Code Playgroud)
或者你可以摆脱循环,使用.SingleOrDefault()
然后测试null,这在意图方面显然是最清楚的,并确保循环执行零次或一次但是更多的代码,它不那么"声明性"而且它不是"可组合":
var attr = p.GetCustomAttributes().OfType<A>().SingleOrDefault();
if (attr != null)
{
...
Run Code Online (Sandbox Code Playgroud)
那么问题是:人们更喜欢上述哪种(或其他建议)?为什么? 大多数习惯于程序代码的程序员自然会更喜欢这个if
语句,但对于那些深入到函数式编程的人来说,你有更好的方法吗?
其他一些语言有清晰的技术来处理这个问题,例如F#的数组模式可以匹配零个,一个或多个,或者失败.是否存在forone
C#语言中的构造的情况,它等同于检查枚举中是否有零或一个然后执行它?
[这里的具体示例是获取自定义属性,其中属性已被标记为不允许多个,但问题更一般地是关于处理零/一个案例.]
显然我会选择SingleOrDefault
因为:
(1)这是一种内置方法.我自己不需要编写额外的方法.先生ZeroOrOne<T>
,你出去了.
(2)一个简单的例子:
var attr = source.SingleOrDefault();
if (attr != null)
{
//do something to attr
}
else
{
//the source is empty
//throw an exception or prompt the user or something equivalent
}
Run Code Online (Sandbox Code Playgroud)
如果你使用其他解决方案,我担心你需要写另一个if
声明来检查source.Count()
.SingleOrDefault
获胜者也是如此.
归档时间: |
|
查看次数: |
205 次 |
最近记录: |