2016-07-05 45 views
4

我有这样一个简单的LINQ查询:是否有可能在LinQ中使用where子句中的条件?

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

然而,物业可以为空,然后我得到一个错误。所以我想知道是否有任何方法检查它是否为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); 
    } 
} 

感谢。

回答

7

是可以延长的λ就是这样:

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

当然,这只会工作,在“正常” LINQ。 Linq-to-sql或-entity查询提供程序可能无法将其转换为sql。

+7

我不喜欢这导致异常查询。那我当然更喜欢一个循环。_“但是,我们建议您避免在查询表达式中调用可能会产生副作用的任何方法,例如修改数据源的内容或引发异常**”_ https://msdn.microsoft.com /en-us/library/bb513730.aspx –

+2

@TimSchmelter我同意,但这就是OP要求的。 –

+1

@TimSchmelter Waht是'myList.Where(x => x.Property?.Property2 == 5)的问题;'? –

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循环的 内容(我favouri TE)或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提供商翻译,如Linq-To-SqlLinq-To-Entities,并违反上述准则。

更新:也许这样的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(); 
+0

您可以先将数据分区为有效/无效,然后在循环之后检查空值。取决于数据量,如果您发现null,则需要*异常。 – Andre