?? Coalesce for empty string?
Solution 1
There isn't a built-in way to do this. You could make your extension method return a string or null, however, which would allow the coalescing operator to work. This would be odd, however, and I personally prefer your current approach.
Since you're already using an extension method, why not just make one that returns the value or a default:
string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number");
Solution 2
C# already lets us substitute values for null
with ??
. So all we need is an extension that converts an empty string to null
, and then we use it like this:
s.SiteNumber.NullIfEmpty() ?? "No Number";
Extension class:
public static class StringExtensions
{
public static string NullIfEmpty(this string s)
{
return string.IsNullOrEmpty(s) ? null : s;
}
public static string NullIfWhiteSpace(this string s)
{
return string.IsNullOrWhiteSpace(s) ? null : s;
}
}
Solution 3
I know this is an old question - but I was looking for an answer and none of the above fit my need as well as what I ended up using:
private static string Coalesce(params string[] strings)
{
return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}
Usage:
string result = Coalesce(s.SiteNumber, s.AltSiteNumber, "No Number");
EDIT: An even more compact way of writing this function would be:
static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
Solution 4
I have a couple of utility extensions that I like to use:
public static string OrDefault(this string str, string @default = default(string))
{
return string.IsNullOrEmpty(str) ? @default : str;
}
public static object OrDefault(this string str, object @default)
{
return string.IsNullOrEmpty(str) ? @default : str;
}
Edit: Inspired by sfsr's answer, I'll be adding this variant to my toolbox from now on:
public static string Coalesce(this string str, params string[] strings)
{
return (new[] {str})
.Concat(strings)
.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}
Solution 5
One of the advantages of the null-coalescing operator is that it short-circuits. When the first part isn't null, the second part isn't evaluated. This can be useful when the fallback requires an expensive operation.
I ended up with:
public static string Coalesce(this string s, Func<string> func)
{
return String.IsNullOrEmpty(s) ? func() : s;
}
Usage:
string navigationTitle = model?.NavigationTitle.
Coalesce(() => RemoteTitleLookup(model?.ID)). // Expensive!
Coalesce(() => model?.DisplayName);
Related videos on Youtube

Nick Craver
I am a Principal Software Engineer at Microsoft working on Azure Functions and related hosting technologies. Formerly the Architecture Lead for Stack Overflow where my day job consisted of being a Developer, Site Reliability Engineer, and DBA. I design and build very fast things in hopes of making life easier for millions of developers. Blog: nickcraver.com/blog Twitter: @Nick_Craver My Developer Story: stackoverflow.com/story/ncraver Disclaimer: I have no idea what I'm talking about, all my answers are guesses!
Updated on October 29, 2021Comments
-
Nick Craver about 1 year
Something I find myself doing more and more is checking a string for empty (as in
""
or null) and a conditional operator.A current example:
s.SiteNumber.IsNullOrEmpty() ? "No Number" : s.SiteNumber;
This is just an extension method, it's equivalent to:
string.IsNullOrEmpty(s.SiteNumber) ? "No Number" : s.SiteNumber;
Since it's empty and not null,
??
won't do the trick. Astring.IsNullOrEmpty()
version of??
would be the perfect solution. I'm thinking there has to be a cleaner way of doing this (I hope!), but I've been at a loss to find it.Does anyone know of a better way to do this, even if it's only in .Net 4.0?
-
Stephen Swensen over 10 yearsJust to tantalize you a bit, you can easily define custom, ad-hoc binary (and unary, for that matter) operators in F#. Here
let (|?) x y = if String.IsNullOrEmpty(x) then y else x
and use it likes.SiteNumber |? "No Number"
.
-
-
Nick Craver almost 13 yearsI think you're right, and this is the cleanest solution currently available that's still readable. I'd love something like a
???
operator in C# 5 though, who knows. -
Jerod Venema over 11 yearsI like option #1 there, although I'd call it something more semantic like Or(), so I could write "string s = s.SiteNumber.Or("Default");"
-
mattmc3 over 11 yearsCalling something
...OrDefault()
would be confusing if it didn't behave like the rest of the framework's...OrDefault()
methods. Like it or not, MS has given a specific meaning to that naming and deviating from that behavior in custom methods is unnecessarily confusing to users of your API. -
bevacqua over 11 yearsand what would the ??? operator do? take default values in addition to nulls? sounds extremely complicated at best
-
Isaac Llopis almost 9 yearsWith lambda expressions maybe? For instance: assume "item" is nullable, then...
item ?? x=> x.ToString() : null;
-
John over 8 yearsI like, but had to fix a compiler error and made it a bit more compact.
-
maraaaaaaaa about 7 years@IsaacLlopis that ends up looking messy-er than OP's original snippet
-
Justin Morgan almost 6 years@druciferre - That just allows you to use
default
as a variable name even though it's a reserved keyword in C#. -
Jimmyt1988 almost 6 yearsWhy do you call this Coalesce when it doesn't bring the values together, but merely selects the one that isn't empty? It's a confusing name dude.
-
Justin Morgan almost 6 years@Jimmyt1988 - Because it approximates the standard T-SQL COALESCE function.
-
Justin Morgan almost 6 years@Jimmyt1988 - Also because it specifically selects the first non-empty function in an arbitrary-length list. It's a subtle detail, but the T-SQL function works the same way. The name makes it intuitive to anyone who knows that function, with or without documentation.
-
Cameron Forward almost 5 yearsBecause Coalesce is the term used by many databases to do the same operation (find first non-null value). Joining strings together is concatenation.
-
JoePC over 3 yearsBest answer if you're
using System.Linq
-
Mariano Luis Villa over 3 yearsThat's elegant, nice job.