1

Why default value of a dictionary class is not same as default value returned by FirstOrDefault using LINQ?

Dictionary<Mode, string> myDict = new Dictionary<Mode, string>() { { Mode.First, "ValueFirst" }, { Mode.Second, "ValueSecond" }, { Mode.Third, "ValueThird" }, { Mode.Forth, "ValueForth" } };
var r1 = myDict.Where(d => d.Value == "Do not exist").FirstOrDefault();
var r2 = default(Dictionary<Mode, string>);

Here Mode is an enum. As a result, r1 is a key-value pair with default values, but r2 is null. Why?

Mayank Garg
  • 21
  • 1
  • 5
  • 2
    Because `FirstOrDefault()` returns a `KeyValuePair`. Not a dictionary. – Gert Arnold Nov 20 '18 at 22:40
  • Or, it can return `default(KeyValuePair)`, which is null - always watch out for nulls on `FirstOrDefault()`. That's related to your second question (about `r2`). If you are working with a reference type (like a `Dictionary`), then `default(YourReferenceTypeGoesHere)` is null - it's always null. If you use `default` on a value type, then it's the zero-ish value, but for reference types, it's always `null` – Flydog57 Nov 20 '18 at 22:44
  • 2
    `KeyValuePair<,>` is a struct, it can never be null. Unless we are talking about Nullable>` which is another type. – Xiaoy312 Nov 20 '18 at 22:47
  • @Xiaoy312: Ooops! Didn't look it up. Makes sense for it to be a value type. Thanks! I've spent a lot of time over the past year cleaning up messes where co-workers called Whatever().FirstOrDefault() and then used the results without a null-check. It's one of my go to code review issues now. – Flydog57 Nov 20 '18 at 22:48
  • 1
    `var r1 = myDict.Where(d => d.Value == "Do not exist").FirstOrDefault();` This is a terrible idea. You can't distinguish whether there was really an entry there or not. If you want to know whether an entry was there you **must** use `ContainsKey` or `TryGetValue`. Or use (worse) `var r1 = myDict.Where(d => d.Value == "Do not exist").Cast?>.FirstOrDefault();` so you can get `null` (which clearly means 'it wasn't there'). – mjwills Nov 20 '18 at 23:02
  • Possible duplicate of [What does default(object); do in C#?](https://stackoverflow.com/questions/2432909/what-does-defaultobject-do-in-c) – mjwills Nov 20 '18 at 23:04

1 Answers1

-1

Use default(KeyValuePair<,>) to check for default value:

var kvp = dict.FirstOrDefault(...);
if (default(KeyValuePair<Mode, string>).Equals(kvp))

Alternatively, you could use an extension method here:

public static class KeyValuePairExtensions
{
    public static bool IsDefault<TKey, TValue>(this KeyValuePair<TKey, TValue> kvp) => default(KeyValuePair<Mode, string>).Equals(kvp);
}

// usage
var kvp = dict.FirstOrDefault(...);
if (kvp.IsDefault())
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44