Null Or Empty Coalescing

In my last blog post, I wrote about the proper way to check for empty enumerations and proposed an IsNullOrEmpty method for collections which sparked a lot of discussion.

This post covers a similar issue, but from a different angle. A very long time ago, I wrote about my love for the null coalescing operator. However, over time, I’ve found it to be not quite as useful as it could be when dealing with strings. For example, here’s the code I might want to write:

public static void DoSomething(string argument) {
  var theArgument = argument ?? "defaultValue";
  Console.WriteLine(theArgument);
}

But here’s the code I actually end up writing:

public static void DoSomething(string argument) {
  var theArgument = argument;
  if(String.IsNullOrWhiteSpace(theArgument)) {
    theArgument = "defaultValue";
  }
  Console.WriteLine(theArgument);
}

The issue here is that I want to treat an argument that consists only of whitespace as if the argument is null and replace the value with my default value. This is something the null coalescing operator won’t help me with.

This lead me to jokingly propose a null or empty coalescing operator on Twitter with the syntax ???. This would allow me to write something like:

var s = argument ??? "default";

Of course, that doesn’t go far enough because wouldn’t I also need a null or whitespace coalescing operator???? ;)

Perhaps a better approach than the PERLification of C# is to write an extension method that normalizes string in such a way you can use the tried and true (and existing!) null coalescing operator.

Thus I present to you the AsNullIfEmpty and AsNullIfWhiteSpace methods!

Here’s my previous example refactored to use these methods.

public static void DoSomething(string argument) {
  var theArgument = argument.AsNullIfWhiteSpace() ?? "defaultValue";

  Console.WriteLine(theArgument);
}

You can also take the same approach with collections.

public static void DoSomething(IEnumerable<string> argument) {
  var theArgument = argument.AsNullIfEmpty() ?? new string[]{"default"};

  Console.WriteLine(theArgument.Count());
}

The following is the code for these simple methods.

public static class EnumerationExtensions {
  public static string AsNullIfEmpty(this string items) {
    if (String.IsNullOrEmpty(items)) {
      return null;
    }
    return items;
  }

  public static string AsNullIfWhiteSpace(this string items) {
    if (String.IsNullOrWhiteSpace(items)) {
      return null;
    }
    return items;
  }
        
  public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
    if (items == null || !items.Any()) {
      return null;
    }
    return items;
  }
}

Another approach that some commenters to my last post recommended is to write a Coalesce method. That’s also a pretty straightforward approach which I leave as an exercise to the reader. :)

What others have said

Requesting Gravatar... Abhishek Jun 16, 2010 2:03 PM
# re: Null Or Empty Coalescing
Naming convention seems incorrect. With the parameter taking single string, the name should be "item" and not "items".
Requesting Gravatar... Jinal Jun 16, 2010 2:08 PM
# re: Null Or Empty Coalescing
Hi,

I have confusion about this method.

public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
if (items == null || items.Any()) {
return null;
}
return items;
}

In this condition should be like this.
if (items == null || !items.Any())

Otherwise if Enumerable has item then it return null.
Requesting Gravatar... Dino Viehland Jun 16, 2010 2:09 PM
# re: Null Or Empty Coalescing
This makes me think of Python rather than Perl and there's no need to be so cryptic. In Python you can do "a or b" where these get checked to see if they're "true" and then yield the 1st value which is true (and lazily evaluates, etc...). In Python "true" is defined as something like:
None (null) is false
Collections > 0 length are true, otherwise false (including strings)
Primitives (int, float, etc...) are true if non-zero

So you can always do "a or b" and get pretty reasonable results - and of course there's an "a and b" which yields the RHS if both are true as well.
Requesting Gravatar... Claus Jun 16, 2010 2:15 PM
# re: Null Or Empty Coalescing
Cool! Ironic thought that you didn't use the null coalescing operator? :)

public static string AsNullIfWhiteSpace(this string item) {
return String.IsNullOrWhiteSpace(item) ? null : item;
}

public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
return (items == null || items.Any()) ? null : items;
}
Requesting Gravatar... Claus Jun 16, 2010 2:19 PM
# re: Null Or Empty Coalescing
Ooops, there's a typo I think, in both your and my code:

public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
return (items == null || items.Any()) ? null : items;
}

Should be:

public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
return (items == null || !items.Any()) ? null : items;
}

to check if the items collection is null, or does NOT contain any elements.
Requesting Gravatar... Kim Jun 16, 2010 2:30 PM
# re: Null Or Empty Coalescing
great Phil! thanks!
Requesting Gravatar... cbp Jun 16, 2010 2:43 PM
# re: Null Or Empty Coalescing
Good idea, I've been wishing for something like this for a while.

Here's an alternative though, which I prefer:

public static string Coalesce(this string value, params string[] with)
{
if (with.Length == 0) return value;
return string.IsNullOrEmpty(value)
? with[0].Coalesce(with.Skip(1).ToArray()) : value;
}


Which allows you to write something like:

myStringA.Coalesce(myStringB, myStringC);
Requesting Gravatar... Damien Guard Jun 16, 2010 3:03 PM
# re: Null Or Empty Coalescing
I tend to use the following LINQ pattern for choosing fallbacks/defaults:

var item = new string[] { item1, item2, "SomeDefault }.First(s => !String.IsNullOrEmpty(s));

[)amien
Requesting Gravatar... RichB Jun 16, 2010 3:31 PM
# re: Null Or Empty Coalescing
AsNullIfEmpty() reminds me of LINQ's DefaultIfEmpty(). Indeed, it may even be a better (homogeneous) name as the null coalescing operator only works on reference types and Default<T>(T) where T is a class will always be null anyway.
Requesting Gravatar... Jake Swenson Jun 16, 2010 3:33 PM
# re: Null Or Empty Coalescing
@Damien Guard I like that! Thanks!
Requesting Gravatar... Craig bovis Jun 16, 2010 7:29 PM
# re: Null Or Empty Coalescing
What happens if the string argument is null though? Surely you'll get an exception since you're trying to run the asnullifwhitespace method on a null reference.
Requesting Gravatar... George Chakhidze Jun 16, 2010 7:48 PM
# re: Coalesce
Here is the Coalesce implementation:

public static T Coalesce<T>(params T[] args) where T : class
{
return args != null ? args.FirstOrDefault(item => item != null) : null;
}

public static Nullable<T> Coalesce<T>(params Nullable<T>[] args) where T : struct
{
return args != null ? args.FirstOrDefault(item => item.HasValue) : null;
}
Requesting Gravatar... George Chakhidze Jun 16, 2010 8:21 PM
# re: Coalesce as Extension Method
as extension method:

public static T Coalesce<T>(this IEnumerable<T> items) where T : class
{
return items != null ? items.FirstOrDefault(item => item != null) : null;
}

public static Nullable<T> Coalesce<T>(this IEnumerable<Nullable<T>> items) where T : struct
{
return items != null ? items.FirstOrDefault(item => item.HasValue) : null;
}
Requesting Gravatar... David S. Jun 16, 2010 10:37 PM
# re: Null Or Empty Coalescing
yesssssssssssssssssssssssssssssssssssss my brain feels good
Requesting Gravatar... Erlis Vidal Jun 16, 2010 10:40 PM
# re: Null Or Empty Coalescing
@Craig: It will work, but this is confusing. It’s true that with this solution you type less, but you can confuse others. If you know that the call is performed to an extension method, then you know that the parameter could be null because that will be translated into

StaticClass.StaticMethod( parameter )

And this is totally valid, parameter could be null. But if you don’t know that the method is an extension one, you will be confused and probably add your own validations around this:


X x = null;
x.SomeMethod();


You’ll expect this to throw an exception.

I like the idea to use extension methods, but sometimes little details like this could cause some trouble.

Have you consider using the extension proposed by Phil as a static method instead?

something as simple as this:

public static class MyConvert {
...
public static string ToNullIfEmpty(string item) {
return String.IsNullOrEmpty(items) ? null : item;
}


Usage:


public static void DoSomething(string argument) {
var theArgument = MyConvert.ToNullIfEmpty(argument) ?? "defaultValue";

Console.WriteLine(theArgument);
}



Requesting Gravatar... Andy Edinborough Jun 17, 2010 12:00 AM
# re: Null Or Empty Coalescing
Isn't it simpler to just have an extension do it all?

public static string NotEmpty(this string input, string otherwise) {
return string.IsNullOrEmpty(input) ? otherwise : input;
}


So you would use it as:

var theArgument = argument.NotEmpty("defaultValue");
Requesting Gravatar... Colin Wiseman Jun 17, 2010 12:10 AM
# re: Null Or Empty Coalescing
var var var var var var var var var var var var var var var!!! Only use var when using Linq, otherwise stop being lazy (IMHO ;-)
Requesting Gravatar... James Hare Jun 17, 2010 12:54 AM
# re: Null Or Empty Coalescing
@Colin: I used to feel the same way about var, but now I love it. It's just way to redundant to always have to write stuff like:

SomeBigClassName myVar = new SomeBigClassName();

Requesting Gravatar... itchi Jun 17, 2010 1:00 AM
# re: Null Or Empty Coalescing
I'm disappointed there were no pictures with some subdued soccer/football innuendo. /insert Khano picture. red card!

And my attempt to participate, a reply to Colin:
var is not necessarily associated with LINQ nor is it a sign of being lazy. stackoverflow.com/.../use-of-var-keyword-in-c

var should_i_use_var = answer ??? true;
Requesting Gravatar... tobi Jun 17, 2010 1:26 AM
# re: Null Or Empty Coalescing
this is my favorite string function:


public static string NullOrWhitespaceToNullAndTrim(this string str)
{
if (string.IsNullOrEmpty(str))
return null;
var trim = str.Trim();
if (trim.Length == 0)
return null;
return trim;
}
Requesting Gravatar... Vince Jun 17, 2010 9:05 AM
# re: Null Or Empty Coalescing
As much as people like to say Extension methods can cause confusion, leads me to belive that some people's memory capacity is limited or non-existant.

If you don't know if a method is an extension method, hover your mouse over the method and VS will show you. After that, next time you see that extension method, you'll remember!

I think using extensions to check for nulls is a great idea.
Requesting Gravatar... Mauricio Jun 17, 2010 11:14 PM
# re: Null Or Empty Coalescing
I actually use such an operator in F# :


let (<||>) a b = if String.IsNullOrWhiteSpace a then b else a
let value = argument <||> "default"


And since operators are regular functions and functions are regular variables I can scope it so I don't disturb outside code with my non-standard operators.
Requesting Gravatar... neronotte Jun 17, 2010 11:53 PM
# re: Null Or Empty Coalescing
my very first extension method was this:

public string OrIfNullOrEmpty(this string text, string defaultValue) {
return String.IsNullOrEmpty(text) ? defaultValue : text;
}

that can be used this way:

myString.OrIfNullOrEmpty("myDefaultValue");

The same approach can be used for an "OrIfNullOrBlank" method... quick&easy!
Requesting Gravatar... jrnail23 Jun 18, 2010 1:20 AM
# re: Null Or Empty Coalescing
Andy Edinborough's extension method (shown above in the comments) is pretty much exactly what I've been using... It's worked quite well for me.
I've also used the same general approach (with generics) for handling null objects (if null, then use provided default value) -- although I'd like to figure a nice way to make it lazy (so that it doesn't evaluate my default value at all unless needed).
Requesting Gravatar... Noah Coad Jun 18, 2010 3:34 AM
# re: Null Or Empty Coalescing
great bit of code, thanks for sharing!
Requesting Gravatar... patridge Jun 21, 2010 2:10 AM
# re: Null Or Empty Coalescing
@jrnail23,

It may not be as pretty to call, but if your fallback value is too painful to evaluate every time, you can use an additional extension method taking a Func<string> (with a lambda calling syntax) so that your "otherwise" is not evaluated unless it is returned. I tweaked it with a hint of @neronotte's naming because it improved readability for me drastically.

public static string IfEmptyUse(this string input, Func<string> otherwise) {
return string.IsNullOrEmpty(input) ? otherwise() : input;
}


called this way

var theArgument = argument.IfEmptyUse(_ => return "defaultValue");
Requesting Gravatar... NC Jun 21, 2010 3:11 PM
# re: Null Or Empty Coalescing
Wow, fail developers here writing Java Syntax in C#.
Requesting Gravatar... Jessica Jun 22, 2010 9:55 AM
# re: Null Or Empty Coalescing
Seems like a lot of work when you already have the ?: ternary operator. Didn't know about that IsNullOrWhitespace function though.. useful!
Requesting Gravatar... cbp Jun 22, 2010 5:05 PM
# re: Null Or Empty Coalescing
Just an update on a lot of the proposed methods above (including mine)...

Be aware that with the following syntax, the second expression is never evaluated if the first expression is not null.

var result = myNotNullString.ToNullIfEmpty()
?? AlternativeMethodDoesNotGetCalled();

With some of the proposed extension methods above, all the alternatives get evaluated at the beginning regardless of which one is null:

var result = myNotNullString
.Coaelsce(ThisWillAlwaysBeEvaluated());

This can lead to some unexpected results.
Requesting Gravatar... Mark Melville Jun 24, 2010 2:27 AM
# re: Null Or Empty Coalescing
I was thinking along the lines of George Chakhidze's implementation. Here's an idea of passing funcs that solves cbp's concern of not evaluating each one:

public static string Coalesce(params Func<string>[] funcs)
{
var candidate = funcs.FirstOrDefault(s => !String.IsNullOrEmpty(s()));
return candidate == null ? null : candidate();
}

called thusly:

string test = Coalesce(ReturnsNonNullString, DoesNotGetCalled, () => "default value");
Requesting Gravatar... Arturo Guzman Jul 01, 2010 11:40 AM
# re: Null Or Empty Coalescing
Decisions... decisions....
+1 Andy Edinborough for the one function to rule them all.
Requesting Gravatar... Steve Calvert Jul 06, 2010 9:00 AM
# re: Null Or Empty Coalescing
Wrestling with C# this way makes me so jealous of javascript sometimes.

var result = value || 'default';

It's nice that 0, '', false, undefined, and null all evaluate to false.

sigh...
Requesting Gravatar... Tuomas Hietanen Jul 07, 2010 12:33 AM
# re: Null Or Empty Coalescing
Hi!
Eric Lippert has a good blog-post about this:

blogs.msdn.com/.../null-is-not-empty.aspx

What do you have to say?

(will show your gravatar)
Please add 7 and 2 and type the answer here: