C# 在LINQ中,选择属性X的所有值,其中X!=无效的

C# 在LINQ中,选择属性X的所有值,其中X!=无效的,c#,linq,C#,Linq,有没有一个简短的方法来写下面的内容?(无需显式写入!=null即可检查null的内容) 如果检查存在,则无法跳过检查。您可以使用。它忽略源序列中的空值。只要使用与MyProperty相同的类型,它就不会过滤掉任何其他内容 // given: // public T MyProperty { get; } var nonNullItems = list.Select(x => x.MyProperty).OfType<T>(); //给定: //公共T MyProperty{g

有没有一个简短的方法来写下面的内容?(无需显式写入
!=null即可检查null的内容)


如果检查存在,则无法跳过检查。

您可以使用。它忽略源序列中的空值。只要使用与
MyProperty
相同的类型,它就不会过滤掉任何其他内容

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

不过,我建议不要这样做。如果要选择非null值,有什么比说“列表中的MyProperties不为null”更明确的呢?

//如果需要检查所有项目的MyProperty是否都不为null

if (list.All(x => x.MyProperty != null))
// do something
if (list.Any(x => x.MyProperty != null))
// do something
//或者,如果您需要检查是否至少有一个项的属性不为null

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

但是您必须始终检查null,您可以定义自己的扩展方法,但我不建议这样做

public static IEnumerable<TResult> SelectNonNull<T, TResult>(this IEnumerable<T> sequence,Func<T, TResult> projection)
{
   return sequence.Select(projection).Where(e => e != null);
}
这只有一个目的,即检查null。对于可为null的值类型,它将转换为不可为null的等效值,因为为不能为null的值保留可为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;
    }
}
公共静态类谓词
{
公共静态bool为null(T值),其中T:class
{
返回值==null;
}
公共静态bool不为null(T值),其中T:class
{
返回值!=null;
}
公共静态bool为null(T?nullableValue),其中T:struct
{
return!nullableValue.HasValue;
}
公共静态bool为NotNull(T?nullableValue),其中T:struct
{
返回nullableValue.HasValue;
}
公共静态bool HasValue(T?nullableValue),其中T:struct
{
返回nullableValue.HasValue;
}
公共静态bool HasNoValue(T?nullableValue),其中T:struct
{
return!nullableValue.HasValue;
}
}

这是根据CodesInChaos的扩展方法改编的。名称较短(
NotNull
),更重要的是,它将类型(
T
)限制为引用带有
的类型,其中T:class

    public static IEnumerable<T> NotNull<T>(this IEnumerable<T> source) where T : class
    {
        return source.Where(item => item != null);
    }
公共静态IEnumerable NotNull(此IEnumerable源代码),其中T:class
{
返回source.Where(item=>item!=null);
}

在不同的选择和忽略空值中获取一列:

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

我知道我参加聚会有点晚了,但我找到了一个非常优雅的解决办法。我编写了一个扩展方法来链接到我的LINQ查询:

public static IEnumerable<T> DiscardNullValues<T>(this IEnumerable<T?> nullable)
    {
        foreach (var item in nullable)
        {
            if (item is not null) yield return item;
        }
    }
public静态IEnumerable丢弃NullValue(此IEnumerable为nullable)
{
foreach(可为null的变量项)
{
如果(项目不为空)生成退货项目;
}
}


工作起来很有魅力。

你有什么理由不想让代码明确说明它的功能吗?我不知道有什么更简单的方法。但即使是你的版本也被普遍认为是“长的”,这很简单。但是,如果列表中的单个项目为空,您将获得NRE。您的where子句必须是项目!=null&&item.MyProperty!=null。@R.Martinho Fernandes对于可空值类型和新添加的可空引用类型,选中null,然后选择仍然会给您一个可空类型。我将听取每个人的建议,并保持原样。但是我把你的答案标记为已接受,因为你告诉了我一些我不知道的事情。我喜欢这一个-它尽可能保持代码的干净,只要你能记住类型是如何工作的!否则,我将使用@CodeInChaos的第二个扩展方法。滥用类型
作为空检查是不直观和糟糕的风格。@CodesInChaos不是真的。对于可为null的值类型和新添加的可为null的引用类型,选中null,然后选择仍然会为您提供一个可为null的类型。除非如果需要表达式树(例如在实体框架中)它不起作用@ricoster如果您需要支持它,请添加一个重载
IQueryable
。如果您否决投票,请说明原因。无缘无故地否决投票只会阻碍捐款。如果有不正确或不完整的地方,就说出来。如果您更喜欢另一个答案,只需向上投票另一个答案。1)我没有向下投票,但对引用类型的限制在我看来不是一个好主意。它阻止在可空值类型上使用此方法,当您想在另一个未受限制的
t
泛型方法中使用此方法时,这尤其令人恼火。2) 我也不太喜欢改名。使用该名称,我希望它检查
source!=null
,如果元素不为null则不为空。@CodesInChaos,感谢您的合理评论。他们很感激。不幸的是,C#(此时)没有nullable的约束。在使用此方法时,我已将类重命名为
Is
,并从所有方法中删除
Is
前缀。在我看来,这使事情更具可读性:
collection.Where(Is.NotNull)。选择…
很高兴我能帮助别人!最好不要使用运算符==和!=对于泛型类型。因为他们可能在类型上有差异。使用ReferenceEquals(value,null)@HorevIvan,假设您不想尊重泛型类型中的
运算符==
逻辑。我认为泛型类型的作者应该确保它对
==
相等性意味着什么。@如果不能重写
=
,只能重载它。但是重载不会影响泛型类型参数。