Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make sure that FirstOrDefault<KeyValuePair> has returned a value

Tags:

c#

linq

Here's a simplified version of what I'm trying to do:

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));

Since 'xyz' is not present in the dictionary, the FirstOrDefault method will not return a valid value. I want to be able to check for this situation but I realize that I can't compare the result to "null" because KeyValuePair is a struc. The following code is invalid:

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

We you attempt to compile the code, Visual Studio throws the following error:

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

How can I check that FirstOrDefault has returned a valid value?

like image 756
desautelsj Avatar asked Aug 26 '09 15:08

desautelsj


People also ask

What is the default value of KeyValuePair?

default equals to null. And default(KeyValuePair<T,U>) is an actual KeyValuePair that contains null, null .

How do you check if a key value pair exists in a dictionary C#?

ContainsKey() Method. This method is used to check whether the Dictionary<TKey,TValue> contains the specified key or not. Syntax: public bool ContainsKey (TKey key);

What is default value FirstOrDefault?

The default value for reference and nullable types is null . The FirstOrDefault method does not provide a way to specify a default value. If you want to specify a default value other than default(TSource) , use the DefaultIfEmpty<TSource>(IEnumerable<TSource>, TSource) method as described in the Example section.

What is KeyValuePair C#?

The KeyValuePair class stores a pair of values in a single list with C#. Set KeyValuePair and add elements − var myList = new List<KeyValuePair<string, int>>(); // adding elements myList. Add(new KeyValuePair<string, int>("Laptop", 20)); myList.


3 Answers

FirstOrDefault doesn't return null, it returns default(T).
You should check for:

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

From MSDN - Enumerable.FirstOrDefault<TSource>:

default(TSource) if source is empty; otherwise, the first element in source.

Notes:

  • If your code is generic it is better to use EqualityComparer<T>.Default.Equals(day, defaultDay), becuase .Equals may be overridden or day could be a null.
  • In C# 7.1 you will be able to use KeyValuePair<int, string> defaultDay = default;, see Target-typed "default" literal.
  • See also: Reference Source - FirstOrDefault
like image 199
Kobi Avatar answered Sep 28 '22 01:09

Kobi


This is the most clear and concise way in my opinion:

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

This completely gets around using weird default value stuff for structs.

like image 40
peaceoutside Avatar answered Sep 28 '22 02:09

peaceoutside


You can do this instead :

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));

and then :

if (day.Key == null) {
    System.Diagnotics.Debug.Write("Couldn't find day of week");
}
like image 32
Jocelyn Marcotte Avatar answered Sep 28 '22 01:09

Jocelyn Marcotte