C# 为null IEnumerables上的Count()返回零
我已经厌倦了使用这样的代码:C# 为null IEnumerables上的Count()返回零,c#,.net,collections,C#,.net,Collections,我已经厌倦了使用这样的代码: var count = 0; if (myEnumerable != null) { count = myEnumerable.Count(); } 这有点迂腐: var count = (myEnumerable ?? new string[0]).Count(); 有没有更整洁的方法?我曾经在IEnumerable上有一个(名字不好的)PhantomCount扩展方法,它使用了我的第一个代码示例,但它有一种气味(除了名称之外)。怎么样 count =
var count = 0;
if (myEnumerable != null)
{
count = myEnumerable.Count();
}
这有点迂腐:
var count = (myEnumerable ?? new string[0]).Count();
有没有更整洁的方法?我曾经在IEnumerable上有一个(名字不好的)PhantomCount扩展方法,它使用了我的第一个代码示例,但它有一种气味(除了名称之外)。怎么样
count = myEnumerable == null? 0 : myEnumerable.Count()
问题实际上在于创建这些可枚举的内容。除非您有很好的理由,否则生成iterable集合的任何内容都应该返回空集合,而不是
null
。这将与目标一致,因此好处是相同的
我的建议是修复生成myEnumerable的任何内容,或者如果您不能做到这一点,请在前面添加一个检查方法,查看它是否为null并做出适当的反应。我不认为使用扩展方法是一个坏主意
public static int NullableCount<T>(this IEnumerable<T> collection)
{
return collection == null ? 0 : collection.Count();
}
public static int NullableCount(此IEnumerable集合)
{
return collection==null?0:collection.Count();
}
只需创建自己的扩展方法,根据需要处理空枚举
public int CountOrNull<T>(this IEnumerable<T> source)
{
return source == null ? 0 : source.Count();
}
这就是扩展方法的优点。即使调用方法的对象是
null
我也会编写自己的扩展方法CountOrZeroForNull
,如其他答案所示,它们仍然可以正常工作
此外。。。而不是:
var count = (myEnumerable ?? new string[0]).Count();
// ^^^^^^^^^^^^^
你可以写:
var count = (myEnumerable ?? Enumerable.Empty<string>()).Count();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
var count=(myEnumerable??Enumerable.Empty()).count();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
这并不能缓解您的特定问题,但它可以避免分配未使用的数组。(Enumerable.Empty
最有可能实现为一个简单的yielbreak
语句。)
虽然它没有其他答案那么专业,但它是最具可读性的。如果返回的值为0,您将采取什么措施 如果这是有趣的,也许您应该使用Haack的
IsNullOrEmpty
扩展方法来扩展IEnumerable
,如下所示:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
{
return items == null || !items.Any();
}
我使用自定义扩展方法:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
...
int count = myEnumerable.EmptyIfNull().Count();
公共静态IEnumerable EmptyIfNull(此IEnumerable源代码)
{
返回源??可枚举的.Empty();
}
...
int count=myEnumerable.EmptyIfNull().count();
2019年,最整洁的方法是var count=myEnumerable?.count()??0;代码>
2021年编辑:
public int CountNullable(此IEnumerable?可枚举)=>
可枚举?.Count()??0;
我有一种感觉,他会要求一个比这个更整洁的,+1尽管如此:)+1我做了完全一样的东西——只是把它命名为CountOrZero
。我个人认为这更清楚。Enumerable.Empty
的当前实现实际上返回一个单例空T[]
数组。@LukeH:我不会想到的。感谢您查找。我不认为这三行代码比一个命名良好的扩展方法更具可读性。是的,我希望避免多次重复相同的检查。这就是我的问题所在。@Noldorin:修复了代码示例中的一个打字错误(注释//4
);也许可以证实这确实是你想要的。@stakx:谢谢;这确实是一个输入错误。请再输入+1。当设计一个API来返回空集合而不是空集合时,这是一个很好的实践,以避免给开发人员带来负担,让他们一直这样做。爱尔兰出产的所有优质葡萄酒列表(空列表)与纳尼亚出产的所有优质葡萄酒列表(空列表,因为纳尼亚不存在)之间存在差异。有时有必要区分空和空。我同意应该倾向于返回空的状态。@Jon:使用null来表示特殊情况就像汽车踩下手刹来表示汽油不足。@Anon使用null来表示空的状态就像,呃,一些非常明显、直接和明智的事情。@Dan。我不同意,我不认为null是无效状态的良好指示器。当“enumerable不存在”和“enumerable存在且为空”都有效并且可以有目的地加以区分时,它是一个很好的指示器。当它们都有效但没有实际差异时,空对象模式中的空枚举会摇动(我最喜欢的一个),当其中一个无效时,我会抛出一个异常。所有这三种情况都可以在经过深思熟虑的代码中发生。+1,我认为这是列出的扩展方法解决方案中最干净的。非常明确的一点是,您假设一个空的可枚举项为空,然后您可以像往常一样处理该可枚举项。
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
{
return items == null || !items.Any();
}
public class ArgumentNullOrEmptyException : ArgumentNullException
{
public ArgumentNullOrEmptyException( string paramName ) : base( paramName )
{}
public ArgumentNullOrEmptyException( string paramName, string message ) : base( paramName, message )
{}
public override string Message
{
get
{
return "Value cannot be null nor empty.{0}Parameter name: {1}".FormatWith( Environment.NewLine, ParamName );
}
}
}
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
...
int count = myEnumerable.EmptyIfNull().Count();