?? Coalesce for empty string?

80,508

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);
Share:
80,508

Related videos on Youtube

Nick Craver
Author by

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, 2021

Comments

  • Nick Craver
    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. A string.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
      Stephen Swensen over 10 years
      Just 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 like s.SiteNumber |? "No Number".
  • Nick Craver
    Nick Craver almost 13 years
    I 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
    Jerod Venema over 11 years
    I 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
    mattmc3 over 11 years
    Calling 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
    bevacqua over 11 years
    and what would the ??? operator do? take default values in addition to nulls? sounds extremely complicated at best
  • Isaac Llopis almost 9 years
    With lambda expressions maybe? For instance: assume "item" is nullable, then... item ?? x=> x.ToString() : null;
  • John over 8 years
    I like, but had to fix a compiler error and made it a bit more compact.
  • maraaaaaaaa
    maraaaaaaaa about 7 years
    @IsaacLlopis that ends up looking messy-er than OP's original snippet
  • Justin Morgan
    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
    Jimmyt1988 almost 6 years
    Why 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
    Justin Morgan almost 6 years
    @Jimmyt1988 - Because it approximates the standard T-SQL COALESCE function.
  • Justin Morgan
    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
    Cameron Forward almost 5 years
    Because Coalesce is the term used by many databases to do the same operation (find first non-null value). Joining strings together is concatenation.
  • JoePC
    JoePC over 3 years
    Best answer if you're using System.Linq
  • Mariano Luis Villa
    Mariano Luis Villa over 3 years
    That's elegant, nice job.

Related