Do you remember that final episode from the fourth season of a great movie "Lost", where Jack, Desmond, Kate with Claire's infant baby, Sawyer, Sayid, Hurley and Frank Lapidus were in a helicopter on their way back to the island? All of a sudden, Ben moved the island to another place.
Jeez. It was a disaster: tranquil waterscape at the very place of a firm land.
In software development, we call this NullReferenceException. Lash of all developers, the high price we pay for not initializing variables and using null as a "sign of unassigned".
How to mitigate this?
A lucky user of Resharper, I'll be talking from that perspective. External annotations framework introduced in 4.0 allows us to benefit from its code analysis. JetBrains guys did a great job annotating system libraries so that you'd get a warning like this one:
And we can
reuse the same technique for our own libraries (to dispel apprehensions: yes,
I’ve created a sample project for download[1]). Two options are
available. You can either apply
annotations attributes directly in the code:
public static int GetLength([NotNull] string text)
{
return text.Length;
}
Or, aternatively, make annotations via XML:
<member name="M:Bar.GetLength(System.String)">
<parameter name="text">
<attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
</parameter>
</member>
Then, if you’re using the method with a potentially null string, Resharper will scream bloody murder (depends on your settings though):
If the
codebase is frequently changing, having attributes directly in the code is probably
better than annotating via XML. Good news for those odd guys who’d better
abstain from having JetBrains.Annotations namespace scattered all over:
1. ReSharper | Options | Code
Annotations
2. Copy default implementation to
clipboard and paste it under your namespace
3. Update default annotations
namespace, restart VS and enjoy
On the
other hand, for a library you can’t modify, XML is the only option.
In this
case, a file [library-name].ExternalAnnotations.xml should be put side by side
with the dll itself, and in order to see the result you’d need to restart
Visual Studio.
Note that XML annotations work only with
dll files, so you have to make sure you reference a library as a dll, not as a
project in a solution.
Anything besides NotNull?
Currently
Resharper provides 9 annotation attributes located in JetBrains.Annotations.dll.
My favorite ones:
·
NotNull
·
CanBeNull
·
TerminatesProgram
·
CannotApplyEqualityOperator
Perhaps,
NotNull and CanBeNull are still most useful. People may argue that the language
itself needs a special not-null indicator (like exclamation mark in Spec#), but
that’s another day question. Well above 60% of all references end up being
not-null anyway, so a lot of code would be mottled with exclamations. Are we
ready for this? Maybe yes – at least, it’s less verbose than using attributes.
A more elegant solution that will never come true is to apply value type syntax
for reference types: all references are implicitly not nulls for the compiler, but a question mark after a type
(ie: «string?» or «Customer?») allows you to set null to the variable.
Footnotes:
[1] – A sample project with External Annotations of Resharper (7 Kb).