2016-07-05 9 views
4

私はこのように簡単なLINQクエリを持っている:LinQの条件付き内部where節を使用することはできますか?

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

ただし、プロパティは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

はいあなたはちょうどそのようラムダを拡張することができます唯一の「ノーマル」LINQで仕事

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

もちろんこの意志を。 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 != null && x.Property.Property2 == 5); 

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

またはこの単純なアプローチをプレーンループもデバッグが容易です。しかし、我々はあなたがそのような変更などの副作用を作成することができ、クエリ 式に任意のメソッドを呼び出す避けることをお勧めします

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

:LINQクエリは、副作用を引き起こすか、例外をスローしてはならないので、これは推奨されますデータソースまたは例外

だから、あなたはすでに(私のfavouriを示してきたforeachループのいずれかを投げるの 内容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-To-SqlまたはLinq-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(); 
+0

最初にデータを有効/無効に分割し、ループの後にヌルをチェックすることができます。データの量によって異なりますが、nullが見つかるとすぐに例外が必要になります。 – Andre