C# if-null-then-null expression
Asked Answered
B

7

61

Just for curiosity/convenience: C# provides two cool conditional expression features I know of:

string trimmed = (input == null) ? null : input.Trim();

and

string trimmed = (input ?? "").Trim();

I miss another such expression for a situation I face very often:

If the input reference is null, then the output should be null. Otherwise, the output should be the outcome of accessing a method or property of the input object.

I have done exactly that in my first example, but (input == null) ? null : input.Trim() is quite verbose and unreadable.

Is there another conditional expression for this case, or can I use the ?? operator elegantly?

Bartolommeo answered 22/11, 2010 at 10:2 Comment(1)
As Jon mentioned below, we can now use null-conditional operators using c# 6.0, like theText?.Trim()Uralian
E
51

Something like Groovy's null-safe dereferencing operator?

string zipCode = customer?.Address?.ZipCode;

I gather that the C# team has looked at this and found that it's not as simple to design elegantly as one might expect... although I haven't heard about the details of the problems.

I don't believe there's any such thing in the language at the moment, I'm afraid... and I haven't heard of any plans for it, although that's not to say it won't happen at some point.

EDIT: It's now going to be part of C# 6, as the "null-conditional operator".

Elihu answered 22/11, 2010 at 10:7 Comment(6)
I wish we have such null-safe dereferencing operator in C# someday.Thomasina
Danny: You could already play with it using dynamics if you accept to lose both type safety and speed. Also the elegant "?" syntax must be replaced by an extension method call. The method could be named AndAnd() to mirror andand.rubyforge.orgKamila
Seems like the C# team might be about to borrow that operator. channel9.msdn.com/Forums/Coffeehouse/…Astri
@JonasElfström: Hooray. I couldn't make Mads's talk, unfortunately - would really like to see this one...Elihu
It seems, there is a plan now: msdn.microsoft.com/hu-hu/magazine/dn802602(en-us).aspxKnitted
Thanks, Jon and @speti43! I took the freedom to correct "conditional null" to "null-conditional" how it is written in the article referencedBartolommeo
T
10

Currently we can only write an extension method if you don't want to repeat yourself, I'm afraid.

public static string NullableTrim(this string s)
{
   return s == null ? null : s.Trim();
}
Thomasina answered 22/11, 2010 at 10:12 Comment(0)
M
10

You can choose between a custom Nullify class or a NullSafe extension method as described here: http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/

The usage will be as follows:

//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name

//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
                       m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
                      .NullSafe( b => b.Name );
Monometallism answered 31/1, 2011 at 5:38 Comment(1)
the NullSafe extension method is just awesome!Leaseback
O
8

As a workaround you can use this which is based on Maybe monad.

public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
    if (instance == null)
        return default(Tout);
    else
        return Output(instance);
}

Use it this way:

int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());
Oeflein answered 22/11, 2010 at 10:45 Comment(1)
This is really great - I used it with the Entity Framework if you're accessing a referenced entity, e.g. var x=Entity1.Entity2.IfNotNull(x=>x.EntityDescription) ?? string.Empty which returns EntityDescription contained in Entity2 which is referenced by Entity1 - or an empty string if any object Entity1 or Entity2 is null. Without IfNotNull you're getting a long and ugly expression. Well done!Darrick
C
6

There's nothing built-in, but you could wrap it all up in an extension method if you wanted (although I probably wouldn't bother).

For this specific example:

string trimmed = input.NullSafeTrim();

// ...

public static class StringExtensions
{
    public static string NullSafeTrim(this string source)
    {
        if (source == null)
            return source;    // or return an empty string if you prefer

        return source.Trim();
    }
}

Or a more general-purpose version:

string trimmed = input.IfNotNull(s => s.Trim());

// ...

public static class YourExtensions
{
    public static TResult IfNotNull<TSource, TResult>(
        this TSource source, Func<TSource, TResult> func)
    {
        if (func == null)
            throw new ArgumentNullException("func");

        if (source == null)
            return source;

        return func(source);
    }
}
Couperin answered 22/11, 2010 at 10:12 Comment(2)
+1 for the NullSafeTrim. The IfNotNull does not convince me, I can't see a gain in terms of readability, only a gain in code complexity.Bartolommeo
@chiccodoro: I'm not convinced by either of these as a solution to this particular "problem", I just thought I'd throw them into the mix! I'd probably use if (foo != null) foo = foo.Trim(); almost every time for this kind of situation, although there are plenty of other situations where it's handy and/or necessary to be able to use an expression rather than a statement.Couperin
C
4

I had the same problem I wrote a few little extension methods:

public static TResult WhenNotNull<T, TResult>(
    this T subject, 
    Func<T, TResult> expression)
    where T : class
{
    if (subject == null) return default(TResult);
    return expression(subject);
}

public static TResult WhenNotNull<T, TResult>(
    this T subject, Func<T, TResult> expression,
    TResult defaultValue)
    where T : class
{
    if (subject == null) return defaultValue;
    return expression(subject);
}

public static void WhenNotNull<T>(this T subject, Action<T> expression)
    where T : class
{
    if (subject != null)
    {
        expression(subject);
    }
}

You use it like this;

string str = null;
return str.WhenNotNull(x => x.Length);

or

IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);

or

object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());

There are also overloads for nullable types.

Cardie answered 22/11, 2010 at 10:19 Comment(2)
Looks interesting, though I'm not sure what you really gain from that. For my eyes it's not more readable and technically introduces more complexity in the compiled code.Bartolommeo
@chiccodoro: in some cases it is more readable, for instance after FirstOrDefault or in similar cases, where you don't need another variable and no if. You can chain them without using lots of variables. It also depends if you allow writing if's in one line or if you force your developers to write it into four lines.Cardie
S
0

I know this was already answered by Jon Skeet but this example might be a little more clear example of the Elvis operator ?. (aka the null-conditional member access operator)

string? someValue = (input == null) ? null : input.Trim()

is equivalent to...

string? someValue = input?.Trim();

"Thank You, Thank You Very Much" - Elvis Presley

Sestina answered 29/6, 2022 at 5:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.