.NET 4.0 Dictionary <TKey, TValue>: value-type key placed in the field for useless checking "null". Does it degrade performance?

For instance:

.method private hidebysig instance void Insert(!TKey key, !TValue 'value', bool add) cil managed { .maxstack 3 .locals init ( [0] int32 num, [1] int32 num2, [2] int32 num3, [3] int32 num4) L_0000: ldarg.1 L_0001: box !TKey L_0006: brtrue.s L_000e L_0008: ldc.i4.5 L_0009: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument) 

This is from the internal method of adding the dictionary <int, Object> in .NET 4.0. Although generalizations are widely touted as helping to avoid value type boxing, why does this system component do this inefficient check for each operation for a value type key? If I understand correctly, this will not only hurt performance, but will always return true (a type with a short value will never be an empty reference)

edit: Summary of Marc's answer for this particular question: the reason is that this dictionary <K, V> implementation refused to use the "null" Nullable <T> instances as keys. Because the instruction in the MSIL field provides special processing for the Nullable <T> value type, validation is not necessarily useless for all value types.

+4
source share
1 answer

A Nullable<T> is a struct / value-type and can be null (depending on your definition of null , but of course it can be a null field). And not all TKey are value-type ( string , perhaps the most common TKey ).

This requires that the key is not null; so you need to check that.

In fact, boxing is not as bad as people think; even in the box, it will be generator-0. This may be a special case through generics (for example, EqualityComparer<T> - through several different subclasses), but it seems redundant.

JIT can also remove null validation. I can tell here, since although this is often cited, I have seen cases where a null check was higher than the JIT ability to remove.

+1
source

All Articles