.Firstをいつ使用し、LINQで.FirstOrDefaultをいつ使用しますか?


824

私は周りを検索しましたが.First、いつ.FirstOrDefaultLINQ を使用したいのか、いつ使用したいのかについて明確な答えが見つかりませんでした。

  • いつ使用し.Firstますか?結果が返されない場合に例外をキャッチしたい場合のみ?

    var result = List.Where(x => x == "foo").First();
  • そして、いつ使用し.FirstOrDefaultますか?結果がない場合に常にデフォルトのタイプが必要な場合は、

    var result = List.Where(x => x == "foo").FirstOrDefault();
  • それで、テイクはどうですか?

    var result = List.Where(x => x == "foo").Take(1);

86
.Firstそして.FirstOrDefaultその引数として取る述語、両方のvar result = List.Where(x => x == "foo").First();ように書き換えることができvar result = List.First(x => x == "foo");
リアンSchmits

59
考慮することを忘れないでくださいSingleSingleOrDefault。私は人々Firstが本当に意味するときに使用するのが嫌いSingleです。)
BartoszKP 2013

19
SingleまたはSingleOrDefaultは、複数の要素が返された場合に例外をスローします。FirstOrDefaultが最も一般的なケースで優れていると思います!
Eric Draven 2016年

21
重要なのは、単一の結果を期待するときにそう言うべきであり、例外はロジックの失敗を示します。
NetMage 2016年

1
また、.FirstOrDefault()常に使用すると、より意味のある例外をスローする機会が得られることも考慮してください。シーケンス例外がスローさ.First()れ、メソッド内で複数の例外がスローされた場合、どのステートメントが問題であるかを識別するのが難しい場合があります。
StingyJack 2017年

回答:


807

First()シーケンスに少なくとも1つの要素があることがわかっているか、または予期している場合に使用します。つまり、シーケンスが空であることが例外的な発生である場合。

FirstOrDefault()要素があったかどうかを確認する必要があることがわかっている場合に使用します。言い換えると、シーケンスが空であっても問題ない場合。チェックの例外処理に依存しないでください。(これは悪い習慣であり、パフォーマンスを低下させる可能性があります)。

最後に、差First()とはTake(1)つまりFirst()ながら、素子自体を戻すTake(1)戻り正確に1つの要素が含まれている要素のシーケンス。


4
@driis-FirstとFirstOrDefaultのどちらかを選択するときに、例外的な例外ガイドラインのマントラを使用できると思います。明確な答えをありがとう。
メトロスマーフ

5
私が追加する唯一のものは、選択しているタイプのデフォルト値が有効な値である可能性がある場合、たとえば、結果がint値0である可能性がある場合、例外を処理することがこれを処理する最良の方法のようです。
PeterBelm 2012

25
それをスクラッチして、私はそれを達成するはるかに良い方法を見つけました、次を使用してください:DefaultIfEmpty(-1).First()
PeterBelm

5
Takeは要素を1つだけ返すのではなく、最大で1つの要素を返します(もちろん、1を指定した場合)。シーケンスが最初は空の場合、0要素を返すこともあります。
SPIRiT_1984

3
@RoyiNamir、はい、取るパラメーターが1である質問のコンテキストではそうです。また、その文の直後の括弧内にも注意しました。
driis

272

.First結果がない場合は例外をスローします。.FirstOrDefaultしない。単にnull(参照タイプ)または値タイプのデフォルト値を返す。(例:0intのように。)ここでの質問は、デフォルトのタイプが必要な場合ではなく、それ以外の場合です。例外を処理するか、デフォルト値を処理しますか?例外は例外的であるべきなのでFirstOrDefault、クエリから結果を取得するかどうかわからない場合に推奨されます。論理的にデータが存在する必要がある場合は、例外処理を検討できます。

Skip()そしてTake()その結果にページングを設定する際に通常使用されています。(最初の10件の結果、次のページに次の10件などを表示するように)

お役に立てれば。


5
@Jeroen-スキップ/テイクを使用するためのより良いユースケースの良い点。
メトロスマーフ

4
.FirstOrDefault参照タイプに対してnullを返す説明の+1 。「デフォルト」オブジェクトがどうなるかについて混乱しました。この答えはそれを解決しました。
Mike Taverne、2018年

115

.First()返される行がない場合は例外をスローし.FirstOrDefault()、デフォルト値(NULL代わりにすべての参照タイプの)。

したがって、準備ができており、起こり得る例外を処理する用意がある場合は問題ありません.First()!= nullとにかく戻り値を確認したい場合.FirstOrDefault()は、より良い選択です。

しかし、それも個人的な好みだと思います。自分にとってより意味のあるものを使用し、コーディングスタイルによりよく適合します。


66

最初()

  1. シーケンスの最初の要素を返します。
  2. 結果に要素がないか、ソースがnullの場合、エラーがスローされます。
  3. 複数の要素が予想され、最初の要素のみが必要な場合は、それを使用する必要があります。

FirstOrDefault()

  1. シーケンスの最初の要素を返します。要素が見つからない場合はデフォルト値を返します。
  2. ソースがnullの場合のみ、エラーをスローします。
  3. 複数の要素が予想され、最初の要素のみが必要な場合は、それを使用する必要があります。結果が空の場合も同様です。

以下に示すように、いくつかのレコードを持つUserInfosテーブルがあります。以下の表に基づいて、例を作成しました...

UserInfoテーブル

First()の使い方

var result = dc.UserInfos.First(x => x.ID == 1);

ID == 1のレコードは1つだけです。このレコード
IDを返す必要があります:1名:マニッシュ姓:Dubeyメール:xyz@xyz.com

var result = dc.UserInfos.First(x => x.FName == "Rahul");   

FName == "Rahul"のレコードが複数あります。最初のレコードを返す必要があります。
ID:7名:Rahul姓:Sharmaメール:xyz1@xyz.com

var result = dc.UserInfos.First(x => x.ID ==13);

ID == 13のレコードはありません。エラーが発生するはずです。
InvalidOperationException:シーケンスに要素が含まれていません

FirstOrDefault()の使用方法

var result = dc.UserInfos.FirstOrDefault(x => x.ID == 1);

ID == 1のレコードは1つだけです。このレコード
IDを返す必要があります:1名:マニッシュ姓:Dubeyメール:xyz@xyz.com

var result = dc.UserInfos.FirstOrDefault(x => x.FName == "Rahul");

FName == "Rahul"のレコードが複数あります。最初のレコードを返す必要があります。
ID:7名:Rahul姓:Sharmaメール:xyz1@xyz.com

var result = dc.UserInfos.FirstOrDefault(x => x.ID ==13);

ID == 13のレコードはありません。戻り値はnullです

First()またはを使用するタイミングを理解するのに役立つことを願っていますFirstOrDefault()


4
私の意見では、「エラーが発生するはずです」という記述。3番目のFirstOrDefault()の例は誤解を招くものです。
Jannik、2015

こんにちは、あなたはよく説明しましたが、結合からデータを取得するときと、そのときに外部キーテーブルにIDが存在しなかったとき、どちらを使用したのか少し混乱していますか?現在、私はFirst()を使用していますが、あなたの答えを読んだ後はわかりません。助けてください
Brijesh Mavani

20

まず第一にTake、完全に異なる方法です。IEnumerable<T>単一ではなくを返しますTでので、それは終わりです。

との間FirstFirstOrDefault、使用する必要がありますFirst、要素が存在することを確認し、存在しない場合はエラーが発生したときにする必要があります。

ちなみに、シーケンスにdefault(T)要素(例:)が含まnullれていて、空の要素との最初の要素を区別する必要がnullある場合は、を使用できませんFirstOrDefault


2
@Mehrdad-素晴らしい点、re:.FirstはIEnumerableを返し、FirstOrDefaultを使用しない場合はいつか。
メトロスマーフ

15

最初:

  • シーケンスの最初の要素を返します
  • 例外をスロー:結果に要素がありません
  • 次の場合に使用:複数の要素が予想され、最初の要素のみが必要な場合

FirstOrDefault:

  • シーケンスの最初の要素、または要素が見つからない場合のデフォルト値を返します
  • 例外をスロー:ソースがnullの場合のみ
  • 次の場合に使用:複数の要素が予想され、最初の要素のみが必要な場合。また、結果が空であっても問題ありません

送信元:http : //www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/


10

注意すべきもう1つの違いは、本番環境でアプリケーションをデバッグする場合、行番号にアクセスできない可能性があるため.First()、メソッド内のどの特定のステートメントが例外をスローしたかを識別するのが難しい場合があることです。

例外メッセージには、問題のデバッグをさらに困難にする、使用した可能性のあるLambda式も含まれません。

そのためFirstOrDefault()、nullエントリが例外的な状況を構成することがわかっている場合でも、常に使用します。

var customer = context.Customers.FirstOrDefault(i => i.Id == customerId);
if (customer == null)
{
   throw new Exception(string.Format("Can't find customer {0}.", customerId));
}

5

最初()

結果に予想される複数の要素が含まれていることがわかっていて、シーケンスの最初の要素のみを使用する必要がある場合。

FirstOrDefault()

FirstOrDefault()は、要素が指定された条件に一致しない場合に、ジェネリックコレクションの基になるタイプのデフォルト値を返すことを除いて、First()と同じです。要素が見つからない場合、InvalidOperationExceptionはスローされません。しかし、要素またはシーケンスのコレクションは、例外をスローするよりもnullです。


こんにちは、あなたはよく説明しましたが、結合からデータを取得するときと、そのときに外部キーテーブルにIDが存在しなかったとき、どちらを使用したのか少し混乱していますか?現在、私はFirst()を使用していますが、あなたの答えを読んだ後はわかりません。助けてください
Brijesh Mavani

4

このタイプの関数は要素演算子に属します。いくつかの有用な要素演算子を以下に定義します。

  1. First / FirstOrDefault
  2. Last / LastOrDefault
  3. シングル/シングルまたはデフォルト

特定の条件に基づいてシーケンスから単一の要素を選択する必要がある場合は、要素演算子を使用します。ここに例があります。

  List<int> items = new List<int>() { 8, 5, 2, 4, 2, 6, 9, 2, 10 };

First()演算子は、条件を満たした後、シーケンスの最初の要素を返します。要素が見つからない場合は、例外がスローされます。

int result = items.Where(item => item == 2).First();

FirstOrDefault()演算子は、条件を満たした後、シーケンスの最初の要素を返します。要素が見つからない場合は、そのタイプのデフォルト値を返します。

int result1 = items.Where(item => item == 2).FirstOrDefault();


わかりやすい例でうまく説明されています。
アルスランバティ


2
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

どちらを使用しますか?例外やプログラムの失敗の恐れではなく、ビジネスロジックによって決定する必要があります。

たとえば、ビジネスロジックで、営業日にはトランザクションをゼロにすることはできないと仮定している場合(想定しているだけ)。次に、このシナリオをスマートプログラミングで処理しようとしないでください。私は常にそのようなコレクションに対してFirst()を使用し、何か他のものがビジネスロジックを台無しにした場合、プログラムを失敗させます。

コード:

var transactionsOnWorkingDay = GetTransactionOnLatestWorkingDay();
var justNeedOneToProcess = transactionsOnWorkingDay.First(): //Not FirstOrDefault()

これについて他の人のコメントを見てほしい。


参照型とnull許容型のデフォルト値はnullです。
dsa

すぐに失敗するのは良いことですが、あなたが説明したシナリオでは、まず、失敗し、例外をキャッチして、意味のあるエラーを返したいと思います。Like catch(InvalidOperationException e){throw new InvalidOperationException( "Cannot have no transaction in a day!"、e)}; しかし、そうです、実際のビジネスロジックの問題への対処を回避するためにデフォルトを使用することは非常に悪いことです。
Mathieson

1

さて、2セントを差し上げましょう。First / Firstordefaultは、2番目のコンストラクターを使用する場合に使用します。それについては説明しませんが、例外を発生させたくないため、常に使用する可能性がある場合です。

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));

ではない正確に。最初のコンストラクタは、1つの項目のみを取得する必要がある場合、または配列ではない値に結果を割り当てるときにコンパイルエラーを回避する必要があり、クエリが正確に1つの結果を返すことが確実な場合に広く使用されます。それは(あなたがいるので、追加.Whereを()使用するのではなく、第二のコンストラクタを使用するより速く見えるかもしれないが考える LINQは、最初に見つけた後、リスト内の項目の評価を停止)、それは常に最初の要素で停止
USR-ローカルΕΨΗΕΛΩΝ

0

他の人は非常によく間の違いを説明してきたFirst()FirstOrDefault()。これらのメソッドのセマンティクスを解釈する上で、さらに一歩踏み出したいと思います。私の意見でFirstOrDefaultは、たくさん使いすぎています。データをフィルタリングするほとんどの場合、論理条件に一致する要素のコレクション、またはユーザー、本、投稿などの一意の識別子による単一の一意の要素を返すことが期待されます。それはなぜそれがFirstOrDefault()コードのにおいであると言うことができるのか、それは何か問題があるからではなく、あまりにも頻繁に使用されているためです。このブログ投稿では、このトピックについて詳しく説明しています。ほとんどの場合IMOSingleOrDefault() ははるかに優れた代替手段であるため、この間違いに注意し、契約と期待を明確に表す最も適切な方法を使用するようにしてください。


-6

コレクションに単一の単純なクエリを実装するための多くの方法をlinqは、sqlで結合を作成するだけで、必要性と必要性​​に応じてフィルターを最初または最後に適用できます。

これは、コレクション内でidを持つ要素を見つけることができる例です。これをさらに追加するには、メソッドFirst、FirstOrDefaultは、コレクションに少なくとも1つのレコードがある場合に理想的に同じ値を返します。ただし、コレクションを空にしても問題ない場合。その後First、例外を返しますが、デフォルトまたはFirstOrDefault戻りnullます。たとえば、intは0を返します。したがって、そのような使用法は個人的な好みであると言われていますが、FirstOrDefault例外処理を回避するために使用する方が良いです。 これはtransactionlistのコレクションを実行する例です

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.