Wednesday, July 27, 2011

I want a conditional dot operator

I was writing earlier about features I'd like to have in the .NET Framework and C#, but I forgot a couple. Earlier I wrote about the "slide operator". Now, I'd like to propose the conditional dot or "null dot" operator.

Some people will say this idea makes the language too complex, but I can't seem to get enough language features. I use just about all of C#'s existing features, including the "hidden" ones. And still I can think of many unsupported features that I know would improve productivity, code clarity, or performance... at least for me.

I think it's okay for C# to have tons of features, but the IDE needs to help teach people what they mean. For example, Visual Studio should show the name of an operator in a tooltip when mousing over it, and show a help page for it if the user puts the cursor on it and presses F1.

C# already has a handy "??" operator which lets you choose a default value in case the "first choice" is null:
Console.WriteLine("Your name is {0}.", firstName ?? "(unknown)");
I use this feature somewhat often. But something's missing. I would like, in addition, a "conditional dot" operator, another kind of null guard that deals with cases where an object you want to access might be null. For example, let's say your class has a reference to another class, and you'd like to inform it when something happened:
if (referenceToAnotherClass != null)
Of course you can't call the method if the referenceToAnotherClass is null. It would be nice if we could shorten this to something like

If the method you want to call returns a value, the "??." operator would substitute null for the return value if the class reference is null. For example,
// firstName might be null; length will be null if firstName is null.
int? length = firstName??.Length;
It would be very natural to combine the "??." operator with the existing "??" operator:
// Equivalent to firstName != null ?  firstName.Length : 0
int length = firstName??.Length ?? 0;
This operator would be most powerful when it is chained together, or used to avoid creating temporary variables:
// If "DatabaseConnection", "PersonTable", and "FirstRow" can all 
// return null, chaining "??." simplifies your code a lot.
var firstName = DatabaseConnection??.Tables.PersonTable??.FirstRow??.Name;

// Equivalent to:
string firstName = null;
var dbc = DatabaseConnection;
if (dbc != null) {
var pt = dbc.Tables.PersonTable;
if (pt != null) {
var fr = pt.FirstRow;
if (fr != null)
firstName = fr.Name;

The operator should also help invoke events:
public event EventHandler Click;
protected void OnClick()
Click??.(this, EventArgs.Empty);
// equivalent to:
if (Click != null)
Click(this, EventArgs.Empty);

// Note: the dot in "??." is still required because "X??(Y)"
// would be indistinguishable from the null coalescing operator.
Somebody implemented a "null dot" extension method that provides this kind of "operator" in C#, except that it only supports one out of the four cases I just described, as it requires that the function you want to call return a reference type; it doesn't support void or struct return values. It's also slightly clumsy, and since it relies on a lambda, it hurts performance. To work well, this feature needs language support.

Right now I am working with code that often converts objects to strings (the objects are usually strings, but may be something else). The object is sometimes null, so I write
string s = (obj ?? "").ToString();
This works fine, but it's less efficient than it could be, because if obj == null, a virtual call to ToString() will be called on the empty string "". If the "null dot" or "conditional dot" operator existed, I would write this code as
string s = obj??.ToString() ?? "";
or even
string s = obj??.ToString();
if a null result is acceptable.

I know that an operator like this exists in some other languages, but I don't which ones at the moment. Anybody remember?

P.S. Microsoft somehow forgot to include a compound assignment operator, which should work like the other compound assignment operators.

twosies += 2; // equivalent to twosies = twosies + 2
doubled *= 2; // equivalent to doubled = doubled * 2
// ensure myList is not null
myList ??= new List<int>(); // myList = myList ?? new List<int>()

1 comment:

Oliver Hanappi said...

In Objective-C sending a message (something like invoking a method) to nil results in nil (or 0 etc.) and will not throw a runtime error. See for details.

I would also like to have this behaviour in C#. I am often confronted with the fact to export data to some files and I usually need to write code like "person.PhoneNumbers.FirstOrDefault().PhoneCenter.Address.Name.Abbreviation...." Normally, I end up with a helper Get.Value(() => x.y) which returns the value of the lamda, but surrounds the whole invocation chain with a try catch in order to catch a NullPointerException.