Вот упрощенная версия того, что я пытаюсь сделать:
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 - это структура. Следующий код недействителен:
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 вернул допустимое значение?
Ответы:
FirstOrDefault
не возвращает null, он возвращаетсяdefault(T)
.Вы должны проверить:
var defaultDay = default(KeyValuePair<int, string>); bool b = day.Equals(defaultDay);
Из MSDN -
Enumerable.FirstOrDefault<TSource>
:Примечания:
EqualityComparer<T>.Default.Equals(day, defaultDay)
, becuase.Equals
могут быть переопределены илиday
может бытьnull
.KeyValuePair<int, string> defaultDay = default;
, см. Типизированный для цели литерал «по умолчанию» .FirstOrDefault
источник
typeof
? Этот код компилируется и работает.default(KeyValuePair<T1, T2>)
это приведет. Хорошо, должно было быть совершенно очевидно, что это приведет к пустому KVP. Но «не очевидно» не хороший подход писать собственные приложения (и моя текущая реализация слишком сложна , чтобы ясно / чисто спровоцировать этот случай), я попробовал его с новым проектом и - на самом деле - он вернулсяKeyValuePair
со свойствамиKey
иValue
существа и то и другоеNULL
.... просто чтобы уберечь других людей эти 5 минут глупости ;-)default
ключевое слово, здесь ее явно не хватает. Благодарность!KeyValuePair
. Если бы у вас был общий код,day.Equals
он даже не является нулевым, и я бы использовалEqualityComparer<T>.Default.Equals(day, defaultDay)
На мой взгляд, это наиболее четкий и лаконичный способ:
var matchedDays = days.Where(x => sampleText.Contains(x.Value)); if (!matchedDays.Any()) { // Nothing matched } else { // Get the first match var day = matchedDays.First(); }
Это полностью обходится с использованием странных значений по умолчанию для структур.
источник
days
это файлDictionary<int,string>
. Так это будет рассматриваться какIEnumerable<KeyValuePair<int,string>>
, то ведет себя , как и ожидалось , когдаAny()
иFirst()
называются. Я предполагаю, что есть другие реализации, которые могут вести себя иначе, чемIEnumerable<>
. Я не знаю, упустил ли я что-то.Вместо этого вы можете сделать это:
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"); }
источник