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

让人想犯罪 __ 提交于 2019-11-26 14:36:28

问题


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.


回答1:


The null propagation operator returns a value. And since you must have a variable on the left hand side of an assignment, and not a value, you cannot use it in this way.

Sure, you could make things shorter by using the tenary operator, but that, on the other hand, doesn't really help the readability aspect.

Joachim Isaksson's comment on your question shows a different approach that should work.




回答2:


As Joachim Isaksson suggested in the comments, I now have a method SetData(Data data) and use it like this:

MyPage1?.SetData(this.data);
MyPage2?.SetData(this.data);
MyPage3?.SetData(this.data);



回答3:


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.




回答4:


Try this Add all your pages to myPageList.

IEnumerable<MyPage> myPageList;

foreach(MyPage myPage in myPageList)
{
if (myPage != null)
    myPage.Data = this.data;
}



回答5:


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




回答6:


A generic SetValue extension method (but only for ref properties) would be:

    public static void SetValue<T>(this T property, T value)
    {
        property = value;
    }

And will be used like

ButtonOrNull?.Visibility.SetValue(Visibility.Hidden);


来源:https://stackoverflow.com/questions/35887106/using-the-null-conditional-operator-on-the-left-hand-side-of-an-assignment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!