Подтвердить что ты не робот

Возвращает ноль для Count() в null IEnumerables

Я устал от использования такого кода:

var count = 0;
if (myEnumerable != null)
{
    count = myEnumerable.Count();
}

И это немного педантично:

var count = (myEnumerable ?? new string[0]).Count();

Есть ли какой-нибудь более аккуратный способ сделать это? У меня когда-то был (сильно названный) метод расширения PhantomCount на IEnumerable < > , который использовал мой первый пример кода, но у него было что-то вроде запаха (помимо имени).

4b9b3361

Ответ 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(); 

Хотя это не так сложно, как другие ответы, это наиболее читаемо.