Есть ли более короткий способ написать следующее? (Что-то, что будет проверять значение null без явной записи != null
)
from item in list
where item.MyProperty != null
select item.MyProperty
Есть ли более короткий способ написать следующее? (Что-то, что будет проверять значение null без явной записи != null
)
from item in list
where item.MyProperty != null
select item.MyProperty
Вы можете использовать оператор OfType
. Он игнорирует нулевые значения в исходной последовательности. Просто используйте тот же тип, что и MyProperty
, и он не будет отфильтровывать что-либо еще.
// given:
// public T MyProperty { get; }
var nonNullItems = list.Select(x => x.MyProperty).OfType<T>();
Я бы советовал против этого. Если вы хотите выбрать ненулевые значения, что может быть более явным, чем сказать, что вы хотите, чтобы "MyProperties из списка не были нулевыми"?
Вы можете определить свой собственный метод расширения, но я бы не рекомендовал этого.
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()
Я стараюсь создать статический класс, содержащий базовые функции для таких случаев. Они позволяют мне писать выражения типа
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;
}
}
Нет способа пропустить проверку, если она существует.
//если вам нужно проверить, не имеют ли все объекты MyProperty null
if (list.All(x => x.MyProperty != null))
// do something
//или если вам нужно проверить, не имеет ли хотя бы один элемент свойства null
if (list.Any(x => x.MyProperty != null))
// do something
Но вы всегда должны проверить null
Это адаптировано из метода расширения 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);
}
получить один столбец в отдельном select и игнорировать нулевые значения:
var items = db.table.Where(p => p.id!=null).GroupBy(p => p.id)
.Select(grp => grp.First().id)
.ToList();