New Fun Blog – Scott Bilas

Take what you want, and leave the rest (just like your salad bar).

Quickie: “NullOr” For Fluent Null-Friendly Member Access

with 2 comments

Are you a fan of C#’s ?? operator like I am? It’s one of the lesser known features of the language, so don’t feel bad if you don’t. I like it because I’m a fan of special language syntax to shorten super common tasks. For example, it lets you change this:

[code lang=”csharp”]
if (obj == null) { obj = defaultValue; }
Console.WriteLine(obj.Name != null ? obj.Name : "<null>");
[/code]

…into this:

[code lang=”csharp”]
obj = obj ?? defaultValue;
Console.WriteLine(obj.Name ?? "<null>");
[/code]

Awesome. That covers a lot of simple use cases. Now, there’s another super common case: accessing members of objects that may or may not be null. Like this:

[code lang=”csharp”]
var name = obj != null ? obj.Name : "<null>";
var lname = obj != null && obj.Name != null ? obj.Name.ToLower() : "<null>";
[/code]

Yuck.

It would be great if C# had a ?. operator that lets you tersely express “return the member if the object is not null, otherwise return null”. Then we could do this instead:

[code lang=”csharp”]
var name = obj?.Name ?? "<null>";
var lname = obj?.Name?.ToLower() ?? "<null>";
[/code]

Well, we can do something like this using one of my favorite tools, the extension method.

[code lang=”csharp”]
public static class ObjectOperations
{
[DebuggerStepThrough]
public static TReturn NullOr<TIn, TReturn>(
this TIn obj, Func<TIn, TReturn> func,
TReturn elseValue = default(TReturn))
where TIn : class
{
return obj != null ? func(obj) : elseValue;
}
}
[/code]

NullOr means “this object can be null or we’ll run the function”. Access to the member can be expressed via a lambda, so the above code can now be expressed like this:

[code lang=”csharp”]
var name = obj.NullOr(_=>_.Name) ?? "<null>";
var lname = obj.NullOr(_=>_.Name).NullOr(_=>_.ToLower()) ?? "<null>";
[/code]

Not bad. It isn’t as terse as I’d like, but it is fluent and more readable, at least to me. Also, being a lambda, you really can put whatever you like in there. It’s not limited to just member access.

Extra

For fun I threw in an “elseValue” clause that lets you provide a default other than null. I haven’t had cause to use this yet, because I find the ?? more readable. Of these, which do you prefer?

[code lang=”csharp”]
var name = obj.NullOr(_=>_.Name) ?? "<null>";
var name = obj.NullOr(_=>_.Name, "<null>");
[/code]

I think I prefer the ?? version because it expresses “no matter what, if the result of this entire chain is null, use this instead”, whereas the default gets a little lost when it’s part of the final function call. It also is more work to rearrange the clauses, should the order of lookups be changed for whatever reason.

(I also wrote this up at StackOverflow and earned myself a nice Necromancer badge.)

October 3rd, 2010 at 5:53 pm

Posted in csharp,quickie

2 Responses to 'Quickie: “NullOr” For Fluent Null-Friendly Member Access'

Subscribe to comments with RSS or TrackBack to 'Quickie: “NullOr” For Fluent Null-Friendly Member Access'.

  1. Very nice post!

    RedMango

    18 Oct 10 at 3:52 am

  2. Thanks for sharing tohguht I would point out that the JSON serializer above causes an infinite loop to occur.I’ll take a minute to debug it this weekend if I can get to it.Cheers!

    Melvin

    26 Oct 15 at 2:43 am

Leave a Reply