.NET 4.0 Dictionary: Value Class Type button for invalid ‘null’ check. Is this harmful?

For example:

.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 the internal Add method from Dictionary. In .NET 4.0. Although Generics are widely touted as helping to avoid boxing of value types, but why does this system component perform inefficient checks on every operation on value type keys? If I understand correctly, this will not only hurt performance, but will always return true (boxed value types will never be a null reference)

Edit: Marc’s answer to this particular question summary: The important reason is This dictionary implementation choice does not allow the use of “null” Nullable instances as keys. Because MSIL box instructions give special treatment to Nullable. Value types, for all value types, the check is not necessarily futile .

Nullable< T> is a struct / value-type, which can be null (depending on Your definition of null; but certainly it can be null). Not all TKeys are value types (strings are probably the most common TKey).

The key here is required to be not empty; So it does need to be verified.

In fact, boxing is not as bad as people think; even if it is boxed, gen-0 will be collected. It can pass generics (e.g. EqualityComparer does-pass some Different subclasses) for special cases, but this seems a bit too much.

JIT can also remove null checks. I can say here that although this is often quoted, I have seen invalid checks go beyond JIT Delete ability.

For example:

.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.ThrowHelp er::ThrowArgumentNullException(valuetype System.ExceptionArgument)

This is the internal Add method from Dictionary. In .NET 4.0. Although generics are widely touted as helping to avoid value types Boxing, but why does this system component perform inefficient checks on every operation of value type keys? If I understand correctly, this will not only hurt performance, but will always return true (boxed value types will never be a null reference)

Edit: Marc’s answer to this particular question summary: The important reason is This dictionary implementation choice does not allow the use of “null” Nullable instances as keys. Because MSIL box instructions give special treatment to Nullable. Value types, for all value types, the check is not necessarily futile .

Nullable< T> is a struct / value-type, which can be null (depending on your definition of null; but certainly it can be null ). Not all TKeys are value types (strings are probably the most common TKey).

The key here is required to be non-empty; so it does need to be verified.

Actually, boxing is not as bad as people think; even if it is boxed, gen-0 will be collected. It can be used for special cases through generics (e.g. EqualityComparer does-through some different subclasses), but this looks It seems a bit too much.

JIT can also delete empty checks. I can say here that although this is often quoted, I have seen cases where invalid checks exceed the ability of JIT to delete.

Leave a Comment

Your email address will not be published.