是否可以在LinQ中使用条件内部where子句?

时间:2016-07-05 08:36:48

标签: c# .net linq

我有这样一个简单的LinQ查询:

myList.Where(x=> x.Property.Property2 == 5);

但是,Property可能为null,然后我收到错误。所以我想知道是否有办法检查它是否为null,如果不为null,进行比较,如果为null,则抛出异常。

因为如果没有,我必须使用foreach来检查每个元素,这样:

List<MyType> myLstResult = new List<MyType>();
foreach(MyType iterator in myList)
{
    if(iterator.Property == null)
    {
        throw new ArgumentNullException();
    }
    if(iterator.Property.Property2 == 5)
    {
        myLstresult.Add(iterator);
    }
}

感谢。

2 个答案:

答案 0 :(得分:7)

是的,您可以像这样扩展lambda:

myList.Where(x=> 
    {
        if (x.Property == null)
            throw new ArgumentNullException();
        return x.Property.Property2 == 5;
    });

这当然只适用于“普通”linq。 Linq-to-sql或-entity查询提供程序可能无法将其转换为sql。

答案 1 :(得分:7)

我会避免异常。

您可以使用新的C#6空传播运算符:

myList.Where(x=> x.Property?.Property2 == 5);

或这个简单的方法:

 myList.Where(x=> x.Property != null && x.Property.Property2 == 5);

但是,如果你真的想抛出一个异常,我会使用一个更容易调试的普通循环。建议这样做,因为LINQ查询不应导致副作用或抛出异常:

https://msdn.microsoft.com/en-us/library/bb513730.aspx

  

但是,我们建议您避免在查询中调用任何方法   表达式,可以创建副作用,如修改   数据源的内容或抛出异常

因此,您已经展示的foreach循环(我最喜欢的)或try-catch

List<MyType> myLstResult = null;
try
{
    myLstResult = myList.Where(x=> x.Property.Property2 == 5).ToList();
}
catch(NullReferenceException nullref)
{
    throw new ArgumentNullException("MyType.Property must not be null", nullref);
}
// ...

Rene has shown另一种我不建议抛出异常的方法。这不能从Linq-To-SqlLinq-To-Entities等LINQ提供程序转换,并违反上述指南。

更新:也许像这样的ThrowIfArgumentNull扩展方法会派上用场:

public static IEnumerable<TSource> ThrowIfArgumentNull<TSource, TNullable>(this IEnumerable<TSource> enumeration, Func<TSource, TNullable> mightBeNullSelector, string argumentName) 
    where TNullable : class
{
    foreach (TSource item in enumeration)
    {
        if (mightBeNullSelector(item) == null)
            throw new ArgumentNullException(argumentName);
        yield return item;
    }
}

你会以这种方式使用它:

List<MyType> myLstresult = myList
    .ThrowIfArgumentNull(x => x.Property, "MyType.Property")
    .Where(x => x.Property.Property2 == 5)
    .ToList();