2

ヌルチェックのどの方法を使用するのが良いでしょうか、そしてその理由は何ですか?

var myVar = myCollection.FirstOrDefault(q => q.Id == 10);
if (myVar != null)
{
   anotherVar = myVar.MyName;
}

また:

var myVar = myCollection.Where(q => q.Id == 10);
if (myVar.Any())
{
   anotherVar = myVar.First().MyName;
}

それとも違いはありませんか?

4

6 に答える 6

1

時期尚早の最適化である可能性がありますが、最初のアプローチは1回の実行のみで済むため、もう少し効率的です。

後でまた怠惰にクエリが必要になる可能性がある場合は、2番目のアプローチを使用しています。それFirstOrDefaultを「終了」します。

于 2013-02-07T20:54:49.250 に答える
1

1つの要素が必要です。

したがってFirstOrDefault()、nullチェックのあるものはより明確です

Where
Any
First

パフォーマンスに関しては、これはほとんどの場合あなたの人生を変えることはありません。しかし、私は最初に「読みやすさ」を考えます。

于 2013-02-07T20:54:50.603 に答える
1

あなたが何をしようとしているのかがはるかに明確なので、私は最初の方法を好みます。

于 2013-02-07T20:54:59.433 に答える
1

null最初のオプションは、チェックに合格したアイテムの結果として壊れることがあります。そのため、一致するアイテムがない場合でも、一致するアイテムはないと思われます。この特定の例には当てはまりませんが、一般的な場合には当てはまります。

ただし、ここでの2番目の例では、ソースシーケンスを2回(場合によっては)繰り返します。1回は結果があるかどうかを確認し、もう1回はその結果を取得します。ソースシーケンスがデータベースクエリを実行して、非常に高額になる可能性のある結果を取得する必要がある場合。このため、このオプションは、処理しているメモリ内コレクションがあり、それが特に大きくない(または必要な最初のアイテムがすぐに見つかる)ことが確実な場合にのみ使用する必要があります。

最初のオプションでこの特定のエッジケースについて心配する必要がある場合、または(必要なものの優れたセマンティック表現のために)Anyを使用する利点を取得したい場合は、次のパターンを使用できます。FirstFirstOrDefault

var myVar = myCollection.Where(q => q.Id == 10)
    .Take(1)
    .ToList();
if (myVar.Any())
{
   anotherVar = myVar.First().MyName;
}

必要に応じて、これを短縮する拡張メソッドを作成できます。

public static IEnumerable<T> FirstOrEmpty<T>(this IEnumerable<T> source)
{
    //TODO: null check arguments
    using (var iterator = source.GetEnumerator())
    {
        if (iterator.MoveNext())
            return new T[] { iterator.Current };
        else
            return Enumerable.Empty<T>();
    }
}

public static IEnumerable<T> FirstOrEmpty<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    return FirstOrEmpty(source.Where(predicate));
}

これにより、次のように書くことができます。

var myVar = myCollection.FirstOrEmpty(q => q.Id == 10);
if (myVar.Any())
{
   anotherVar = myVar.First().MyName;
}
于 2013-02-07T20:56:41.117 に答える
0

Whereの後にFirstOrDefaultが続く式を使用する傾向があります。

var myVar = myCollection.Where(x => x.Id==10).FirstOrDefault();
if (myVar != null)
{
   anotherVar = myVar.MyName;
}

Raphael Althausが上で指摘したように、1つの変数をnullチェックする必要があります。私の意見では、最初に条件を使用してクエリを実行し、次に最初の変数が存在する場合はそれを選択してチェックする必要があります。

于 2013-02-07T21:05:16.963 に答える
0

2つのアプローチ異なります。ここではILです。

FirstOrDefault +if (myVar != null)

IL_0067:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_006C:  brtrue.s    IL_007F
IL_006E:  ldnull      
IL_006F:  ldftn       b__0
IL_0075:  newobj      System.Func<<>f__AnonymousType0<System.Int32,System.String>,System.Boolean>..ctor
IL_007A:  stsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_007F:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0084:  call        System.Linq.Enumerable.FirstOrDefault  <-----
IL_0089:  stloc.2     // myVar
IL_008A:  ldloc.2     // myVar
IL_008B:  brfalse.s   IL_0094
IL_008D:  ldloc.2     // myVar
IL_008E:  callvirt    <>f__AnonymousType0<System.Int32,System.String>.get_MyName
IL_0093:  stloc.1     // anotherVar
IL_0094:  ldloc.1     // anotherVar
  • FirstOrDefault

ここで+if (myVar.Any())

IL_0067:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_006C:  brtrue.s    IL_007F
IL_006E:  ldnull      
IL_006F:  ldftn       b__0
IL_0075:  newobj      System.Func<<>f__AnonymousType0<System.Int32,System.String>,System.Boolean>..ctor
IL_007A:  stsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_007F:  ldsfld      UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0084:  call        System.Linq.Enumerable.Where   <-----
IL_0089:  stloc.2     // myVar
IL_008A:  ldloc.2     // myVar
IL_008B:  call        System.Linq.Enumerable.Any     <-----
IL_0090:  brfalse.s   IL_009E
IL_0092:  ldloc.2     // myVar
IL_0093:  call        System.Linq.Enumerable.First   <-----
IL_0098:  callvirt    <>f__AnonymousType0<System.Int32,System.String>.get_MyName
IL_009D:  stloc.1     // anotherVar
IL_009E:  ldloc.1     // anotherVar
  • どこ
  • どれでも
  • 初め

マイクロ最適化のように見えますが、最初の列挙はでの単一の列挙であるため、より高速である必要がありFirstOrDefaultますが、後の列挙子にWhere含まれる要素がそれほど多くないq.Id == 10場合は、実際には重要ではありません。2つの間で、私は間違いなく最も明確な構文を好みます。

ところで、私は大ファンです...代わりにnullusignはどうですか?if (myVar != default(T))

于 2013-02-08T03:44:09.093 に答える