在赋值的左侧使用空条件运算符

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

我有几个页面,每个页面都有一个名为 Data 的 属性。在另一页上,我将此数据设置为:

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

是否可以在 MyPage 上使用空条件运算符?我在想这样的事情:

MyPage?.Data = this.data;

但是当我这样写的时候,出现如下错误:

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

我知道这是因为 MyPage 可能为空,左侧不再是变量。

并不是说我不能像已经拥有它那样使用它,而是我只是想知道是否有可能对此使用 null 条件运算符。

空传播运算符 returns 一个值。并且由于您必须在赋值的左侧有一个变量,而不是一个值,所以您不能以这种方式使用它。

当然,您可以使用三元运算符来缩短内容,但另一方面,这并不能真正提高可读性。

Joachim Isaksson 对您的问题的评论显示了一种应该有效的不同方法。

试试这个 将所有页面添加到 myPageList。

IEnumerable<MyPage> myPageList;

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

正如 Joachim Isaksson 在评论中建议的那样,我现在有一个方法 SetData(Data data) 并像这样使用它:

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

通用的 SetValue 扩展方法(但仅适用于 ref 属性)是:

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

并且会像

一样使用
ButtonOrNull?.Visibility.SetValue(Visibility.Hidden);

我想到了以下扩展,

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

可以全局调用;这仅适用于 public 个属性。

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

以下改进版本适用于任何东西,

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

也可以全局调用,

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

但是扩展名称有些误导,因为 Action 并不完全需要赋值。

派对来晚了,但我是带着类似的问题来到这篇文章的。我采用了 SetValue 方法的想法并创建了一个通用扩展方法,如下所示:

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

示例用法,用于附加和分离事件处理程序:

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

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

希望有人觉得它有用:)

您可以使用扩展方法

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