在LINQ中,选择属性X的所有值,其中X!= null

Ily*_*gan 40 c# linq

是否有更短的方式来写下面的内容?(在没有明确写入的情况下检查null的东西!= null)

from item in list 
where item.MyProperty != null 
select item.MyProperty
Run Code Online (Sandbox Code Playgroud)

R. *_*des 57

您可以使用该OfType运算符.它忽略源序列中的空值.只需使用相同的类型MyProperty,它不会过滤掉任何其他内容.

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

我会建议不要这样做.如果你想选择非空值,那么可能比你想要"列表中的非属性的MyProperties"更明确吗?

  • 滥用`OfType`作为空检查是不直观和坏的风格. (46认同)
  • 我会听取每个人的建议并保持原样.但我把你的答案标记为已被接受,因为你告诉了我一些我不知道的事情. (2认同)

Cod*_*aos 34

您可以定义自己的扩展方法,但我不建议这样做.

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

我不喜欢这个,因为它混合了两个问题.使用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);
}
Run Code Online (Sandbox Code Playgroud)

这只有一个目的,检查null.对于可空值的类型,它会转换为不可为空的等价物,因为保留可空的包装器对于不能为null的值是没用的.

使用此方法,您的代码变为:

list.Select(item => item.MyProperty).WhereNotNull()
Run Code Online (Sandbox Code Playgroud)

  • @RicoSuter如果需要支持,请添加`IQueryable &lt;T&gt;`的重载。 (2认同)

Ant*_*ony 12

我倾向于创建一个包含这些案例的基本函数的静态类.他们允许我写表达式

var myValues myItems.Select(x => x.Value).Where(Predicates.IsNotNull);
Run Code Online (Sandbox Code Playgroud)

以及谓词函数的集合:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在使用这个方法时,我已经将类重命名为`Is`并从所有方法中删除了`Is`前缀.它使事物更具可读性IMO:`collection.Where(Is.NotNull).Select ...` (6认同)

aba*_*hev 5

无法跳过检查是否存在。