Unique ways to use the null coalescing operator
Another advantage is that the ternary operator requires a double evaluation or a temporary variable.
Consider this, for instance:
string result = MyMethod() ?? "default value";
while with the ternary operator you are left with either:
string result = (MyMethod () != null ? MyMethod () : "default value");
which calls MyMethod twice, or:
string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");
Either way, the null coalescing operator is cleaner and, I guess, more efficient.
I've found it useful in two "slightly odd" ways:
- As an alternative for having an
out
parameter when writingTryParse
routines (i.e. return the null value if parsing fails) - As a "don't know" representation for comparisons
The latter needs a little bit more information. Typically when you create a comparison with multiple elements, you need to see whether the first part of the comparison (e.g. age) gives a definitive answer, then the next part (e.g. name) only if the first part didn't help. Using the null coalescing operator means you can write pretty simple comparisons (whether for ordering or equality). For example, using a couple of helper classes in MiscUtil:
public int Compare(Person p1, Person p2)
{
return PartialComparer.Compare(p1.Age, p2.Age)
?? PartialComparer.Compare(p1.Name, p2.Name)
?? PartialComparer.Compare(p1.Salary, p2.Salary)
?? 0;
}
Admittedly I now have ProjectionComparer in MiscUtil, along with some extensions, which make this kind of thing even easier - but it's still neat.
The same can be done for checking for reference equality (or nullity) at the start of implementing Equals.
Well, first of all, it's much easier to chain than the standard ternary operator:
string anybody = parm1 ?? localDefault ?? globalDefault;
vs.
string anyboby = (parm1 != null) ? parm1
: ((localDefault != null) ? localDefault
: globalDefault);
It also works well if a null-possible object isn't a variable:
string anybody = Parameters["Name"]
?? Settings["Name"]
?? GlobalSetting["Name"];
vs.
string anybody = (Parameters["Name"] != null ? Parameters["Name"]
: (Settings["Name"] != null) ? Settings["Name"]
: GlobalSetting["Name"];
I've used it as a lazy load one-liner:
public MyClass LazyProp
{
get { return lazyField ?? (lazyField = new MyClass()); }
}
Readable? Decide for yourself.