В LINQ выберите все значения свойства X, где X!= Null
Есть ли более короткий способ написать следующее? (Что-то, что будет проверять значение null без явной записи != null
)
from item in list
where item.MyProperty != null
select item.MyProperty
Ответы
Ответ 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();