Возвращает ноль для Count() в null IEnumerables
Я устал от использования такого кода:
var count = 0;
if (myEnumerable != null)
{
count = myEnumerable.Count();
}
И это немного педантично:
var count = (myEnumerable ?? new string[0]).Count();
Есть ли какой-нибудь более аккуратный способ сделать это? У меня когда-то был (сильно названный) метод расширения PhantomCount на IEnumerable < > , который использовал мой первый пример кода, но у него было что-то вроде запаха (помимо имени).
Ответы
Ответ 1
Проблема в том, что создает эти перечисления. Если у вас нет действительно веской причины, все, что генерирует итерируемую коллекцию, должно возвращать пустую коллекцию вместо null
. Это согласуется с Null-Object-Pattern, поэтому преимущества одинаковы.
Мое предложение заключалось бы в том, чтобы исправить все, что производит myEnumerable
, или если вы не можете этого сделать, добавьте способ проверки раньше, чтобы увидеть, является ли он нулевым и реагирует соответствующим образом.
Ответ 2
Как насчет
count = myEnumerable == null? 0 : myEnumerable.Count()
Ответ 3
Я не думаю, что использование метода расширения - плохая идея.
public static int NullableCount<T>(this IEnumerable<T> collection)
{
return collection == null ? 0 : collection.Count();
}
Ответ 4
Я использую собственный метод расширения:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
...
int count = myEnumerable.EmptyIfNull().Count();
Ответ 5
Просто создайте свой собственный метод расширения, который обрабатывает нулевые перечисления, как вы пожелаете.
public int CountOrNull<T>(this IEnumerable<T> source)
{
return source == null ? 0 : source.Count();
}
Затем вы можете просто использовать:
var list1 = new int[] { 1, 2, 3, 4 };
var list2 = (int[])null;
var count1 = list1.CountOrNull(); // 4
var count2 = list2.CountOrNull(); // 0
Это замечательная вещь о методах расширения. Они все еще работают нормально, даже если объект, по которому (вы, кажется,) вызываете метод, находится null
.
Ответ 6
Я бы также написал свой собственный метод расширения CountOrZeroForNull
, как показано в других ответах.
Кроме того... Вместо:
var count = (myEnumerable ?? new string[0]).Count();
// ^^^^^^^^^^^^^
вы можете написать:
var count = (myEnumerable ?? Enumerable.Empty<string>()).Count();
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
Это не облегчает вашу конкретную проблему, но это обходит выделение неиспользуемого массива. (Enumerable.Empty<T>
скорее всего реализуется как простой оператор yield break
.)
Ответ 7
Какие действия вы предпринимаете, если возвращаемое значение равно 0?
Если это интересно, возможно, вам следует использовать метод расширения Haack IsNullOrEmpty
для IEnumerable
следующим образом:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
{
return items == null || !items.Any();
}
Ссылка http://haacked.com/archive/2010/06/10/checking-for-empty-enumerations.aspx
Отправленный как комментарий к блогу, вы также найдете класс Exception
, который я написал, чтобы пойти с этим:
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 );
}
}
}
Ответ 8
В 2019 году самый простой способ сделать это - var count = myEnumerable?.Count()?? 0;
var count = myEnumerable?.Count()?? 0;
,
Ответ 9
var count = 0;
if (myEnumerable != null)
count = myEnumerable.Count();
Хотя это не так сложно, как другие ответы, это наиболее читаемо.