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를 사용할 수 없습니다.
Kobi

ooops ... 맞아요. 제가 기억에서 타이핑하고 있었는데 분명히 실수를했습니다. 지적 해 주셔서 감사합니다.
desautelsj

1
아마도 : var days = new Dictionary <int, string> ();
Even Mien

답변:


156

FirstOrDefaultnull을 반환하지 않으면 default(T).
다음 사항을 확인해야합니다.

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

에서 MSDN -Enumerable.FirstOrDefault<TSource> :

source가 비어 있으면 default ( TSource ); 그렇지 않으면 source 의 첫 번째 요소입니다 .

노트:


17
+1, KeyValuePair는 참조 유형 (클래스) 또는 널 입력 가능 값 유형이 아닌 값 유형 (구조체)이므로 널이 될 수 없습니다.
Lucas

6
@ paper1337-고마워.하지만 어디가 빠졌 typeof니? 이 코드는 컴파일되고 작동합니다.
Kobi

3
어떤 default(KeyValuePair<T1, T2>)결과가 나올지 명확하지 않았기 때문에 여기에 왔습니다 . 좋습니다. 빈 KVP가되는 것은 분명 했어야합니다. 그러나 "명백한 것"으로 적절한 응용 프로그램을 작성할 수있는 좋은 방법 아니다 (나의 현재 구현 / 명확하게이 사건을 유발 명확하게 너무 복잡하다), 나는 새로운 프로젝트를 시도하고 - 사실 - 그것은 반환 KeyValuePair속성 KeyValue존재 둘 다 NULL.... 단지 다른 사람들을 보호하기 위해이 5 분의 어리 석음 ;-)
Nicolas

@Nicolas-여기에 어리 석음이 없습니다. 항상 자신을 확인하고 코드를 이해하고 있는지 확인하는 것이 좋습니다. default키워드 에 대한 링크를 추가했는데 여기에 분명히 누락되어 있습니다. 감사!
Kobi

1
@JeffBridgman-정말 좋은 지적입니다! 특히 여기서는 불가능합니다 KeyValuePair.. 당신은 일반적인 코드를 가지고 있다면, day.Equals심지어 널 안전하지, 내가 사용하는 것EqualityComparer<T>.Default.Equals(day, defaultDay)
코비

54

이것은 제 생각에 가장 명확하고 간결한 방법입니다.

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

이것은 구조체에 대해 이상한 기본값을 사용하여 완전히 돌아갑니다.


13
이것의 문제는 (구현에 따라) 열거 가능한 날짜가 두 번 열거되거나 더 나쁘게 Any ()와 First () 호출 사이에 다른 값을 반환 할 가능성이 있다는 것입니다
Ray Booysen

@RayBooysen ToArray 또는 ToList를 호출하면 문제가 해결되고 Count / Length 및 Indexer를 사용할 수 있습니다.
콘솔

1
때문에 @ 레이의 대답은 여기에 적용되지 않습니다 days입니다 Dictionary<int,string>. 그것은가로 간주됩니다 그래서 IEnumerable<KeyValuePair<int,string>>, 다음 때 예상대로 행동 Any()하고 First()라고합니다. .NET과 다르게 동작 할 수있는 다른 구현이 있다고 생각합니다 IEnumerable<>. 내가 뭔가 빠졌는지 모르겠어요.
Emanuele Bellini

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.