如何确保FirstOrDefault <KeyValuePair>已返回值

des*_*lsj 83 c# linq

这是我正在尝试做的简化版本:

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));
Run Code Online (Sandbox Code Playgroud)

由于KeyValuePair变量中不存在'xyz',因此FirstOrDefault方法不会返回有效值.我希望能够检查这种情况,但我意识到我无法将结果与"null"进行比较,因为KeyValuePair是一个结构.以下代码无效:

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

我们尝试编译代码,Visual Studio会抛出以下错误:

Operator '==' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<int,string>' and '<null>'
Run Code Online (Sandbox Code Playgroud)

如何检查FirstOrDefault是否返回了有效值?

Kob*_*obi 144

FirstOrDefault不返回null,它返回default(T).
你应该检查:

var defaultDay = default(KeyValuePair<int, string>);
bool b = day.Equals(defaultDay);
Run Code Online (Sandbox Code Playgroud)

来自MSDN -Enumerable.FirstOrDefault<TSource>:

如果source为空,则为default(TSource); 否则,源中的第一个元素.

笔记:

  • +1,KeyValuePair是值类型(struct),不是引用类型(类)或可空值类型,因此它不能为null. (15认同)
  • @ paper1337 - 谢谢,但我在哪里缺少`typeof`?此代码编译和工作. (6认同)
  • 我来到这里是因为尚不清楚`default(KeyValuePair &lt;T1,T2&gt;)`会导致什么。好的,应该很明显,它将导致空KVP。但是由于“变得明显”不是编写适当应用程序的好方法(并且我当前的实现太复杂而无法清楚/明确地引发这种情况),我在一个新项目中进行了尝试,并且-实际上-它返回了一个`KeyValuePair`,属性`Key`和`Value`均为`NULL` ....这只是为了让其他5分钟的愚蠢者感到安全;-) (2认同)

pea*_*ide 51

在我看来,这是最简洁明了的方式:

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

这完全绕过结构使用奇怪的默认值.

  • 问题在于,有可能(取决于实现)可枚举的天数将被枚举两次,甚至更糟,在Any()和First()调用之间返回不同的值 (13认同)
  • 请注意,@Ray 的答案在这里不适用,因为“days”是一个“Dictionary&lt;int,string&gt;”。因此,它将被视为“IEnumerable&lt;KeyValuePair&lt;int,string&gt;&gt;”,然后在调用“Any()”和“First()”时按预期运行。我猜想还有其他实现的行为可能与“IEnumerable&lt;&gt;”不同。我不知道我是否遗漏了一些东西。 (2认同)