30

What is default value of KeyValuePair<string, int>?

e.g. I am running a LINQ query and returning FirstOrDefault() value from it

KeyValuePair<string, int> mapping = (from p in lstMappings
    where p.Key.Equals(dc.ColumnName, StringComparison.InvariantCultureIgnoreCase)
    select p).FirstOrDefault();

if (mapping != null)
{ 

}

how to check if mapping object is null/blank
(I am getting compile time error in above code Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<string,int>' and '<null>')

PS: lstMappings is of type

List<KeyValuePair<string, int>>
Nitin Sawant
  • 7,278
  • 9
  • 52
  • 98
  • 1
    That's very poor use of a LINQ query. You shouldn't be using LINQ at all there. If you want to be able treat your keys in a case-insensitive manner the you should be providing your own IEqualityComparer that will do just that. You would then simply use the ContainsKey method of the Dictionary to determine whether there's a match and, if there is, get the value by that key. – jmcilhinney Jan 28 '14 at 11:30
  • duplicate of [The default for KeyValuePair](http://stackoverflow.com/q/1641392/3834) – Graviton Aug 05 '14 at 07:32

3 Answers3

47

The default value of any type T is default(T), so for 100% theoretical accuracy you would write

if (!mapping.Equals(default(KeyValuePair<string, int>))) {
    // ...
}

Since KeyValuePair is a struct (i.e. a value type) you cannot compare it to null. Irrespective of that, comparing values with == is wrong as a default approach because if used on reference types it normally checks for reference equality.

Patty
  • 123
  • 7
Jon
  • 428,835
  • 81
  • 738
  • 806
  • "comparing values with `==` is wrong as a default approach because if used on reference types it normally checks for reference equality" ??? I think it's quite standard practice? – neonblitzer Sep 17 '20 at 11:33
24

KeyValuePair<T, T> is a struct. As such, it is a value type, cannot be null, and will be initialized with the member’s default values.

For KeyValuePair<string, int>, this will be the null string, and the int value 0.

KeyValuePair<string, int> kvp = default(KeyValuePair<string, int>);
Console.WriteLine(kvp.Key == null); // True
Console.WriteLine(kvp.Value == 0); // True

Just like I used default(T) to intialize the object with its default value, you can also use it to compare your result with it to find out if it’s the default value or not:

if (!mapping.Equals(default(KeyValuePair<string, int>)))
{ … }

The other alternative, if you don’t want to work with the default value anyway, would be to just use First and check for the exception which is thrown when there isn’t a result value.

poke
  • 369,085
  • 72
  • 557
  • 602
  • 1
    Using your example of comparing to the default, I get `Operator '!=' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair' and 'System.Collections.Generic.KeyValuePair'`. Otherwise, good answer. – xr280xr Apr 01 '15 at 23:49
5

KeyValuePair<TKey, TValue> is a structure, therefore a value type and cannot be null. Default value of a struct is stuct populated with default values of it's members. In this example it would be:

new KeyValuePair(null, 0)


That should answer your direct question, but a more elegant way to do comparison you are trying to do is to use default keyword.

if (mapping != default(KeyValuePair<string, int>))
{ 
    // Mapping has default value
}

You could use equivalent code for any other type beside KeyValuePair<TKey, TValue>. For reference types default will return null, otherwise it will return default value of value type.

Nikola Radosavljević
  • 6,871
  • 32
  • 44