【问题标题】:Using the null-conditional operator on the left-hand side of an assignment在赋值左侧使用空条件运算符
【发布时间】:2016-06-23 13:30:48
【问题描述】:

我有几页,每页都有一个名为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;

但是当我这样写时,我得到以下错误:

赋值的左侧必须是变量、属性或索引器。

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

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

【问题讨论】:

标签: c# null-conditional-operator


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我想出了以下扩展,

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

      可以全局调用;这仅适用于公共财产。

      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 并不完全需要分配。

      【讨论】:

        【解决方案4】:

        参加聚会有点晚了,但我带着类似的问题来到这篇文章。我借鉴了 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);
        

        希望有人觉得它有用:)

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

            你可以使用扩展方法

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

            【讨论】:

              【解决方案7】:

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

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

              并且会像这样使用

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

              【讨论】:

              • 你测试过这个吗?这绝对不会起作用...T property 必须是 ref 参数才能使更改生效,因为您唯一要做的就是在函数内设置属性的本地副本,而您不能拥有this ref 扩展方法,C# 也不允许 ref 访问属性(与 VB 不同,这实际上是一种耻辱)。
              • 哦,你说得非常对 ? - 它只适用于 ref 参数(所以在我的情况下它总是......偶然)
              • @MikeMarynowski:实际上你现在可以拥有ref this 扩展方法(但阻止将属性传递给 ref 参数的限制仍然存在)
              • @BenVoigt 不适合不受约束的T。值类型只能有 this ref
              猜你喜欢
              • 2017-07-16
              • 2015-06-12
              • 2016-06-08
              • 1970-01-01
              • 2016-08-20
              相关资源
              最近更新 更多