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

В LINQ выберите все значения свойства X, где X!= Null

Есть ли более короткий способ написать следующее? (Что-то, что будет проверять значение null без явной записи != null)

from item in list 
where item.MyProperty != null 
select item.MyProperty
4b9b3361

Ответ 1

Вы можете использовать оператор OfType. Он игнорирует нулевые значения в исходной последовательности. Просто используйте тот же тип, что и MyProperty, и он не будет отфильтровывать что-либо еще.

// given:
// public T MyProperty { get; }
var nonNullItems = list.Select(x => x.MyProperty).OfType<T>();

Я бы советовал против этого. Если вы хотите выбрать ненулевые значения, что может быть более явным, чем сказать, что вы хотите, чтобы "MyProperties из списка не были нулевыми"?

Ответ 2

Вы можете определить свой собственный метод расширения, но я бы не рекомендовал этого.

public static IEnumerable<TResult> SelectNonNull<T, TResult>(this IEnumerable<T> sequence,Func<T, TResult> projection)
{
   return sequence.Select(projection).Where(e => e != null);
}

Мне не нравится этот, потому что он смешивает две проблемы. Проецирование с помощью Select и фильтрация нулевых значений являются отдельными операциями и не должны объединяться в один метод.


Я бы предпочел определить метод расширения, который проверяет, не является ли элемент не null:

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> sequence)
{
   return sequence.Where(e => e != null);
}

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> sequence)
    where T : struct
{
   return sequence.Where(e => e != null).Select(e => e.Value);
}

Это имеет только одну цель, проверяя значение null. Для типов с нулевыми значениями он преобразуется в эквивалент, не имеющий нулевых значений, поскольку бесполезно сохранять обнуляемую оболочку для значений, которые не могут быть нулевыми.

С помощью этого метода ваш код будет выглядеть следующим образом:

list.Select(item => item.MyProperty).WhereNotNull()

Ответ 3

Я стараюсь создать статический класс, содержащий базовые функции для таких случаев. Они позволяют мне писать выражения типа

var myValues myItems.Select(x => x.Value).Where(Predicates.IsNotNull);

И набор предикатных функций:

public static class Predicates
{
    public static bool IsNull<T>(T value) where T : class
    {
        return value == null;
    }

    public static bool IsNotNull<T>(T value) where T : class
    {
        return value != null;
    }

    public static bool IsNull<T>(T? nullableValue) where T : struct
    {
        return !nullableValue.HasValue;
    }

    public static bool IsNotNull<T>(T? nullableValue) where T : struct
    {
        return nullableValue.HasValue;
    }

    public static bool HasValue<T>(T? nullableValue) where T : struct
    {
        return nullableValue.HasValue;
    }

    public static bool HasNoValue<T>(T? nullableValue) where T : struct
    {
        return !nullableValue.HasValue;
    }
}

Ответ 4

Нет способа пропустить проверку, если она существует.

Ответ 5

//если вам нужно проверить, не имеют ли все объекты MyProperty null

if (list.All(x => x.MyProperty != null))
// do something

//или если вам нужно проверить, не имеет ли хотя бы один элемент свойства null

if (list.Any(x => x.MyProperty != null))
// do something

Но вы всегда должны проверить null

Ответ 6

Это адаптировано из метода расширения CodesInChaos. Имя короче (NotNull) и, что более важно, ограничивает тип (T) ссылочными типами с помощью where T : class.

    public static IEnumerable<T> NotNull<T>(this IEnumerable<T> source) where T : class
    {
        return source.Where(item => item != null);
    }

Ответ 7

получить один столбец в отдельном select и игнорировать нулевые значения:

 var items = db.table.Where(p => p.id!=null).GroupBy(p => p.id)
                                .Select(grp => grp.First().id)
                                .ToList();