Search code examples
c#exceptionnullreferenceexceptionkeynotfoundexception

Useless Exceptions (NullReferenceException, KeyNotFoundException)


I find the C# exceptions very annoying, because they provide so less information. What is the reason for this?

NullReferenceException or KeyNotFoundExceptions are hard to debug and sometimes you don´t get a linenumber in the stacktrace. Why can the exception itself not provide more informations?

For example:

private Dictionary<string, object> Properties = null;

public void Process(string key)
{ 
    var item = this.Properties[key];
    ....
}

When "Properties"is null I get a NullReferenceException:

"System.NullReferenceException: Object reference not set to an instance to an object"

Why I do not get:

"System.NullReferenceException: Object reference 'Properties' not set to an instance to an object"

This would be more usefull and the CLR does know, which reference is null.

The same when I pass a non existent key e.g. Process("dummy"):

"System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary"

Why I do not get:

"System.Collections.Generic.KeyNotFoundException: The key 'dummy' was not present in the dictionary"

The CLR knows, which key was passed and not found.

I try to debug such errors (which illegal keys are passed) in an productive environment and made the code more robust like:

private Dictionary<string, object> Properties = null;

public void Process(string key)
{ 
  if (this.Properties != null)
  {
    if (this.Properties.ContainsKey(key))
    {
        var item = this.Properties[key];
        ...
    }
    else
    {
        throw new KeyNotFoundException(string.Format("The key '{0}' was not found.", key));
    }
  }
  else
  {
    throw new NullReferenceException(string.Format("The object 'Properties' is null."));
  }
}

But why I have to do this, normally the CLR could tell me what was going wrong in detail. I cannot wrap all codepieces like this to get more informations when an exception happens.


Solution

  • For your KeyNotFoundExceptions, you can create your own dictionary class that throws more meaningful messages (I recommend you try to extend KeyNotFoundException and throw that), or you can use TryGetValue and throw a meaningful exception.

    The NullReferenceException one, however, is much more complicated: you assume that the CLR knows that the thing is called Properties, but it's not so simple: consider this.GetSomething(abc).DoSomething(), where GetSomething(abc) returns null. What is the object that's null? It doesn't have a name. And sometimes, especially in Release-optimized code, names for variables or other things that might be null are generated.

    You should be debugging with test cases, Asserts, breakpoints, and other debug-mode code, not expecting that you can always get a good enough exception message to debug production code. E.g. even if you know that the key "dummy" was passed in, you might not have enough information to know why that key was bad, or was passed in.