Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary.FirstOrDefault() how to determine if a result was found

Tags:

c#

.net

linq

I have (or wanted to have) some code like this:

IDictionary<string,int> dict = new Dictionary<string,int>(); // ... Add some stuff to the dictionary.  // Try to find an entry by value (if multiple, don't care which one). var entry = dict.FirstOrDefault(e => e.Value == 1); if ( entry != null ) {     // ^^^ above gives a compile error:    // Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and '<null>' } 

I also tried changing the offending line like this:

if ( entry != default(KeyValuePair<string,int>) )  

But that also gives a compile error:

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

What gives here?

like image 584
Eric Petroelje Avatar asked Mar 24 '11 20:03

Eric Petroelje


People also ask

What does FirstOrDefault return if not found?

The major difference between First and FirstOrDefault is that First() will throw an exception if there is no result data for the supplied criteria whereas FirstOrDefault() returns a default value (null) if there is no result data.

What is the default value returned by 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.


1 Answers

Jon's answer will work with Dictionary<string, int>, as that can't have a null key value in the dictionary. It wouldn't work with Dictionary<int, string>, however, as that doesn't represent a null key value... the "failure" mode would end up with a key of 0.

Two options:

Write a TryFirstOrDefault method, like this:

public static bool TryFirstOrDefault<T>(this IEnumerable<T> source, out T value) {     value = default(T);     using (var iterator = source.GetEnumerator())     {         if (iterator.MoveNext())         {             value = iterator.Current;             return true;         }         return false;     } } 

Alternatively, project to a nullable type:

var entry = dict.Where(e => e.Value == 1)                 .Select(e => (KeyValuePair<string,int>?) e)                 .FirstOrDefault();  if (entry != null) {     // Use entry.Value, which is the KeyValuePair<string,int> } 
like image 61
Jon Skeet Avatar answered Oct 04 '22 20:10

Jon Skeet