如何确保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方法将不会返回有效值。我希望能够检查这种情况,但是我意识到我无法将结果与“ null”进行比较,因为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已返回有效值?


1
您那里有一个错误,但我认为这是一个复制粘贴的事情:天不是列表,并且您不能在KeyValuePair上使用添加。
Kobi

糟糕...您是正确的,我是从内存中键入内容,显然我犯了一个错误。感谢您指出。
desautelsj

1
可能是:var days = new Dictionary <int,string>();
甚至Mien

Answers:


155

FirstOrDefault不返回null,而是返回default(T)
您应该检查:

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

MSDN-Enumerable.FirstOrDefault<TSource>

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

笔记:


16
+ 1,KeyValuePair是一个值类型(结构),而不是引用类型(类)或可为空的值类型,因此它不能为null。
卢卡斯2009年

6
@ paper1337-谢谢,但是我在哪里想念typeof?该代码可以编译和运行。
科比

3
我来这里是因为我不清楚,这default(KeyValuePair<T1, T2>)将导致什么。好的,应该很明显,它将导致空KVP。但是,随着“是明显的”不写正确应用的好方法(和我目前的执行情况太复杂,显然/干净惹这种情况下),我有一个新的项目尝试过了, -实际上-它返回一个KeyValuePair包含属性KeyValue存在都NULL....只是为了让其他人安全这5分钟的愚蠢;-)
Nicolas

@Nicolas-这里没有愚蠢。检查自己并确保您了解您的代码始终是一个好主意。我已经为default关键字添加了一个链接,这里显然不存在该链接。谢谢!
科比

1
@JeffBridgman-真的很不错!在这里特别不可能,因为我们正在与合作KeyValuePair。如果您有通用代码,day.Equals甚至不是null安全的,那我会用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
这样做的问题是,有可能(取决于实现方式)枚举的日子可能会被枚举两次,甚至更糟,从而在Any()和First()调用之间返回不同的值
Ray Booysen 2012年

@RayBooysen调用ToArray或ToList解决了此问题,您可以使用Count / Length和Indexer。
控制台

1
请注意,@ Ray的答案不适用于此处,因为daysDictionary<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");
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.