C# if-null-then-null expression

C#.NetConditional OperatorConditional Expressions

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

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".

Solution 2 - C#

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();
}

Solution 3 - C#

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 );

Solution 4 - C#

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());

Solution 5 - C#

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);
    }
}

Solution 6 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionchiccodoroView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Cheng ChenView Answer on Stackoverflow
Solution 3 - C#naiemView Answer on Stackoverflow
Solution 4 - C#QrystaLView Answer on Stackoverflow
Solution 5 - C#LukeHView Answer on Stackoverflow
Solution 6 - C#Stefan SteineggerView Answer on Stackoverflow