chuckd
chuckd

Reputation: 14600

Is the c# coalescence the same as an if statement when setting to null?

Are these two statements the same?

if (dep.BirthDate.HasValue) {
  myObj.GetType().GetProperty("birthdate").SetValue(myObj, (DateTime)dep.BirthDate, null);
}


myObj.GetType().GetProperty("birthdate").SetValue(myObj, dep.BirthDate ?? null, null);

I only want to set the birthdate when it has a value, but I'd like to do it in 1 line.

Upvotes: 0

Views: 80

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236278

As @IanKemp suggested, you cannot avoid if-check when you want to skip the property assignment. Do not confuse with assigning default value.

The simplest solution is to encapsulate a nullable value check and property assignment into single operation. To avoid passing PropertyInfo around, you can use the extension method:

public static class ReflectionExtensions
{
    public static void SetValueIfNotNull<T>(this PropertyInfo prop, object obj, T? maybe)
        where T : struct
    {
        if (maybe.HasValue)
            prop.SetValue(obj, maybe.Value);
    }
}

Usage:

myObj.GetType().GetProperty("birthdate").SetValueIfNotNull(myObj, dep.BirthDate);

Or if you work a lot with nullable values and property settings is not the only thing you do, then you can write a nullable extension which will bring your code back to non-nullable path:

public static class NullableExtensions
{
    // Note that action has non-nullable argument
    public static void Invoke<T>(this Nullable<T> nullable, Action<T> action)
        where T: struct
    {
        if (nullable.HasValue)
            action(nullable.Value);
    }
}

This approach swaps things around - now you can invoke actions on the value of nullable variable if nullable has value:

dep.BirthDate.Invoke(date => myObj.GetType().GetProperty("birthday").SetValue(myObj, date));

Or even this way if you'll invoke single argument functions

dep.BirthDate.Invoke(myObj.SetProperty<DateTime>("birthday"));

Upvotes: 2

Christopher
Christopher

Reputation: 9824

First of all, this does sound like a Speed Question. So, the speed rant: https://ericlippert.com/2012/12/17/performance-rant/

Secondly, the only price you get for putting a lot of things into one line are:

  • a heck of a time to read it
  • a heck of a time to understand it
  • somehow a even worse time trying to debug it

The first one has 6 (six) places were either of the null Reference exceptions might hit. Also a cast and reflection. It is a Exception breeding ground. Whoever will have to debug that line 6 months from now, will get nightmares from it. And that can be you.

Code readability and debugability should come first. Try to limit it to 1 operation/code line, whose result you assign to a temporary variable, to get usefull Exceptions. Never be worried about the performance impact of temporary variables. Between the Compiler, the JiT Compiler and dead code detection those will propably cut out in release builds anyway.

Upvotes: 1

Related Questions