Using the null-conditional operator on the left-hand side of an assignment

Viewed 12078

I have a few pages, each with a property named Data. On another page I'm setting this data like this:

if (MyPage1 != null)
    MyPage1.Data = this.data;
if (MyPage2 != null)
    MyPage2.Data = this.data;
if (MyPage3 != null)
    MyPage3.Data = this.data;

Is there any possibility to use the null-conditional operator on MyPage? I'm thinking of something like this:

MyPage?.Data = this.data;

But when I write it like this, I get the following error:

The left-hand side of an assignment must be a variable, property or indexer.

I know it's because MyPage could be null and the left-hand side wouldn't be a variable anymore.

It's not that I cannot use it like I have it already but I just want to know if there's any possibility to use the null-conditional operator on this.

7 Answers

I came up with the following extension,

public static class ObjectExtensions
{
    public static void SetValue<TValue>(this object @object, string propertyName, TValue value)
    {
        var property = @object.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
        if (property?.CanWrite == true)
            property.SetValue(@object, value, null);
    }
}

Which may be called globally; this only works on public properties.

myObject?.SetValue("MyProperty", new SomeObject());

The following improved version works on anything,

public static void SetValue<TObject>(this TObject @object, Action<TObject> assignment)
{
    assignment(@object);
}

And may also be called globally,

myObject?.SetValue(i => i.MyProperty = new SomeObject());

But the extension name is somewhat misleading as the Action does not exclusively require an assignment.

Rather late to the party, but I came to this article with a similar issue. I took the idea of the SetValue method and created a generic extension method, as below:

/// <summary>
/// Similar to save navigation operator, but for assignment. Useful for += and -= event handlers. 
/// If <paramref name="obj"/> is null, then <paramref name="action"/> is not performed and false is returned.
/// If <paramref name="obj"/> is not null, then <paramref name="action"/> is performed and true is returned.
/// </summary>
public static bool SafeAssign<T>(this T obj , Action<T> action ) where T : class 
{
  if (obj is null) return false;
  action.Invoke(obj);
  return true;
}

Example usage, for attaching and detaching event an handler:

public void Attach() => _control.SafeAssign(c => c.MouseDown += Drag);

public void Detach() => _control.SafeAssign(c => c.MouseDown-= Drag);

Hope somebody finds it useful :)

You can Use Extension Method

 public static void NCC<T>(this T instance, System.Action<T> func)
        where T : class
{
        if (instance != null)
        {
            func(instance);
        }
}

MyPage1.NCC(_=>_.Data = this.data);
Related