2012-01-08 47 views
2

我发现自己写之前以下一遍又一遍:检查空可枚举循环

if (myEnumerable != null) { 
    foreach (var element in myEnumerable) { 
     DoSomething(element); 
    } 
} 

这是乏味我想列举每次检查NULL,有没有更好的办法?例如,是否有一种方法来重写枚举器返回“Enumerable.Empty”而不是NULL?

+0

更好的是什么意思?我没有看到你在这里想要改进的东西。 – Tudor 2012-01-08 20:03:35

+0

为什么你经常首先迭代潜在的空序列?我几乎从不需要在循环之前检查null,因为在大多数情况下,'null'首先是我的函数的一个无效参数,并且经过验证。 – CodesInChaos 2012-01-08 20:05:20

回答

6

那么,理想的设计你的代码,以便它不能为空。另外,创建一个扩展方法:

public static class EnumerableEx 
{ 
    public static IEnumerable<T> EmptyIfNull(this IEnumerable<T> source) 
    { 
     return source ?? Enumerable.Empty<T>(); 
    } 
} 

然后:

foreach (var element in myEnumerable.EmptyIfNull()) 
    DoSomething(element); 
} 

这是大致相同Darin的做法,但空合并运算符移动到一个扩展方法。

+1

T中的T是什么EmptyArray = ...? – dtb 2012-01-08 20:04:52

+0

@dtb:嘎,你说得对。编辑... – 2012-01-08 20:05:13

+0

当然,如果您所使用的序列的静态类型与“IEnumerable ”不同,这会显着降低枚举速度。 – CodesInChaos 2012-01-08 20:07:04

8

您可以使用null-coalescing operator

foreach (var element in myEnumerable ?? Enumerable.Empty<Foo>()) { 
    DoSomething(element); 
} 

,但更好的方法是确保您随时随地都取这个IEnumerable<T>从不会返回null这是传统的方式,在.NET可枚举工作。

+0

非常好的建议。我们可以更进一步:你认为我们可以重写枚举器并返回“空”而不是null? – desautelsj 2012-01-08 20:04:39

+2

@desautelsj,不,对我来说,更进一步的是修复返回这个枚举的代码,以便它永远不会返回null。 – 2012-01-08 20:06:09

+0

@desautelsj:重写*哪个*枚举器?你正在谈论一个变量,它是以null开头的 - 你只能调用除扩展方法之外的其他任何东西。我们不知道什么是返回空引用开始。 – 2012-01-08 20:06:13

1

扩展方法:

public static EnumerableExtensions 
{ 
    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable) 
    { 
    return enumerable ?? Enumerable.Empty<T>(); 
    } 
} 

然后,你可以做

foreach (var element in myEnumerable.EmptyIfNull()) 
{ 
    DoSomething(element); 
} 
0

不幸的是检查null是生活中的事实......但它可以更容易。我已经写了一个名为ValidWithItems的扩展来检查null以及在非null时有占位项,以便实际枚举项。

public static class EnumerableExtensions 
{ 

    /// <summary>Does two checks, if not null and if it has items.</summary> 
    /// <returns>True if it is not null and has at least 1 item.</returns> 
    public static bool ValidWithItems<T>(this IEnumerable<T> target) 
    { 
     return ((target != null) && (target.Any())); 
    } 
}