FirstOrDefault <KeyValuePair>が値を返したことをどのように確認できますか


91

これが私がやろうとしていることの簡単なバージョンです:

var days = new Dictionary<int, string>();
days.Add(1, "Monday");
days.Add(2, "Tuesday");
...
days.Add(7, "Sunday");

var sampleText = "My favorite day of the week is 'xyz'";
var day = days.FirstOrDefault(x => sampleText.Contains(x.Value));

「xyz」はディクショナリに存在しないため、FirstOrDefaultメソッドは有効な値を返しません。この状況をチェックしたいのですが、KeyValuePairが構造体であるため、結果を「null」と比較できないことに気付きました。次のコードは無効です:

if (day == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}

コードをコンパイルしようとすると、Visual Studioから次のエラーがスローされます。

Operator '==' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<int,string>' and '<null>'

FirstOrDefaultが有効な値を返したことをどのように確認できますか?


1
あなたはそこにバグがありますが、私はそれがコピーと貼り付けのことだと思います:日はリストではなく、KeyValuePairでaddを使用することはできません。
コビ

おっと...あなたは正しいです。私はメモリから入力していたので、間違いを犯しました。指摘してくれてありがとう。
desautelsj 2009

1
おそらく:var days = new Dictionary <int、string>();
Mienでさえ

回答:


155

FirstOrDefaultnullを返さず、を返しますdefault(T)
次の点を確認する必要があります。

var defaultDay = default(KeyValuePair<int, string>);
bool b = day.Equals(defaultDay);

MSDNEnumerable.FirstOrDefault<TSource>から-

default(TSource)ソースが空の場合。それ以外の場合は、sourceの最初の要素。

ノート:


16
+ 1、KeyValuePairは値型(構造体)であり、参照型(クラス)やnull許容値型ではないため、nullにすることはできません。
ルーカス

6
@ paper1337-ありがとう、でもどこに行けないのtypeof?このコードはコンパイルして機能します。
コビ、

3
default(KeyValuePair<T1, T2>)結果がどうなるかはっきりしないので、ここに来ました。OK、KVPが空になることは明らかでした。しかし、「明白であることが」適切なアプリケーションを作成するための良い方法ではない(と私の現在の実装は明らかに/きれいにこのケースを誘発するにはあまりにも複雑である)として、私は新しいプロジェクトでそれを試してみました-確かに-それは返さKeyValuePairプロパティを持つKeyValueされて両方NULL....この5分の愚かさを他の人たちの安全を守るために;-)
Nicolas

@Nicolas-ここでは愚かさはありません。自分で確認し、コードを理解していることを常に確認することをお勧めします。defaultキーワードへのリンクを追加しましたが、ここには明らかにありません。ありがとう!
Kobi 2016

1
@JeffBridgman-それは本当に良い点です!具体的には、で作業しているため、ここでは不可能KeyValuePairです。あなたがジェネリックコードを持っていて、ヌルセーフでday.Equalsさえないなら、私は使用したでしょうEqualityComparer<T>.Default.Equals(day, defaultDay)
Kobi

53

これは私の意見では最も明確で簡潔な方法です:

var matchedDays = days.Where(x => sampleText.Contains(x.Value));
if (!matchedDays.Any())
{
    // Nothing matched
}
else
{
    // Get the first match
    var day = matchedDays.First();
}

これは、構造体の奇妙なデフォルト値を使用して完全に回避します。


13
これに関する問題は、列挙可能な日が2回列挙される可能性があるか(実装によって異なります)、さらに悪いことに、Any()呼び出しとFirst()呼び出しの間で異なる値を返す可能性があることです
Ray Booysen

@RayBooysen ToArrayまたはToListの呼び出しは問題を解決し、Count / Lengthおよびインデクサーを使用できます。
コンソール14

1
ので、@レイの答えは、ここでは適用されないことに注意daysですDictionary<int,string>。したがって、と見なされIEnumerable<KeyValuePair<int,string>>Any()First()が呼び出されたときに期待どおりに動作します。とは異なる動作をする他の実装があると思いIEnumerable<>ます。何か足りないのかわかりません。
エマヌエーレベリーニ

0

代わりにこれを行うことができます:

var days = new Dictionary<int?, string>();   // replace int by int?
days.Add(1, "Monday");
days.Add(2, "Tuesday");
...
days.Add(7, "Sunday");

var sampleText = "My favorite day of the week is 'xyz'";
var day = days.FirstOrDefault(x => sampleText.Contains(x.Value));

その後 :

if (day.Key == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.