【问题标题】:C# ?? operator in property, how it works?C# ??属性中的运算符,它是如何工作的?
【发布时间】:2015-05-15 18:11:16
【问题描述】:

我无法理解它是如何工作的。

private Person _user;

private Person User
{
  get
  {
    return _user ?? ( _user = GetUser() );
  }
}

我第一次引用 User 属性时,_user 为 null,所以它返回 (_user = GetUser())??????

我错过了什么?

【问题讨论】:

  • msdn.microsoft.com/en-us/library/ms173224.aspx 首先仔细阅读。它的目的是检查 _user 是否为空,如果是,则在您的情况下返回右侧 (_user = GetUser()) 的值
  • 旁注:Lazy<T> 可能是表达延迟初始化的更好方式。
  • @Alexei:应用程序在 Framework 3.5 中。还是谢谢!
  • @JohnSaunders,我认为这不是链接问题的重复,OP 对赋值表达式感到困惑,恕我直言。
  • 我肯定不能根据 OP 所说的来判断。

标签: c# operator-keyword


【解决方案1】:

首先,它是null-coalescing operator,如果不是null,则返回左侧操作数,否则返回右侧操作数。

return _user ?? ( _user = GetUser() );

如果_usernull,它返回GetUser 方法返回的内容,并将私有字段设置为它。

所以它的工作原理是:

  1. GetUser 返回分配给 _user 的值
  2. 赋值表达式 (_user = GetUser()) 返回值。

见:How assignment expression returns value.

【讨论】:

  • 所以我们今天学习了一些关于赋值表达式的知识!谢谢哈比布!
  • @Habib 没问题。 +1,因为我最喜欢您的回答,因为它解释了所有内容,但又简明扼要,并链接了所有材料以供进一步调查。
  • 很好的解释。我要补充的是,ReSharper 等工具可用作学习资源的一个领域。如果您有功能等效的 express(使用 if(_user == null) ... ),Resharper 将提供重构它。这样可以很容易地看到等效的 sn-ps。在 C#6.0 中,它可以替换为表达式主体 private Person User => _user ?? (_user = GetUser());也许是糖太多了?
【解决方案2】:

该代码与此基本相同:

private Person _user;

private Person User
{
    get
    {
        if (_user == null) _user = GetUser();
        return _user;
    }
}

工作原理

null 合并运算符 (??) 如果对象不为 null,则返回该对象,否则返回运算符另一侧的任何内容。所以声明:

return _user ?? ( _user = GetUser() );

说,“返回_user,除非它为空,在这种情况下返回赋值结果( _user = GetUser() )”。这是为_user 赋值并在同一行中返回该赋值的巧妙方法。

话虽如此,一些开发人员会争辩说,我上面写的第一个方法使用两行而不是一行,可读性更高(意图更清晰)并且更易于维护。

【讨论】:

  • 这是不正确的。如果该行是这样的:return _user ?? GetUser();,则在调用 GetUser 时不会更新 _user,但仍会返回来自 GetUser 的值。在您的情况下,如果我们扩展该行,它将是:if(_user == null) GetUser(); return _user;,它不会返回 GetUser() 的值,而是 _user 的值为 null。
  • @Nautious 不确定我是否关注你,我认为你误读了我的代码。如果_user 为空,我正在做一个分配,那么我将返回_user(在任何一种情况下都不会为空)。在我对正在发生的事情的描述中,我还说它返回“分配的结果”,这再次意味着不是null
  • 如果与 OP 问题中的代码行相比,您的代码是正确的:(return _user ?? (_user = GetUser());)。但是,您的代码不正确,代表什么?意味着,因为如果我们尝试用您的替代方法解释此代码行:return _user ?? GetUser(),那么当使用 ??将返回 GetUser 中的值,但使用您的代码会丢失该值,并返回 _user 的值为 null 的值。
  • @Nautious 您的代码在功能上与 Rufus 解决方案相同。 GetUser() 的值也不会丢失。 "_user = GetUser()" 注意 _user 被赋予 GetUser() 的值。也许您应该将所有三个代码 sn-ps(问题、您的解决方案和 rufus 的解决方案)放入 IDE 并在进一步“更正”之前进行验证?
  • @Nautious,不,价值并没有像我之前解释的那样丢失。你没看到作业吗??
【解决方案3】:

它被称为Null Coalescing 运算符。如果它左侧的对象为空,它将执行右侧的表达式。

这里右边的操作符设置了_user对象,所以下次引用User就不再执行右边了,返回_user

【讨论】:

    【解决方案4】:

    赋值表达式= 既对_user 进行赋值,又返回被赋值的值,因此它可以像表达式一样使用。

    【讨论】:

    • 不是我的反对意见,而是返回值的赋值表达式。但这只是术语和措辞。
    【解决方案5】:

    所以在 Habibs 提示之后,我在 MSDN 中找到了这个。 = Operator (C# Reference) 哪里清楚...

    “赋值运算符 (=) 将其右侧操作数的值存储在由其左侧操作数表示的存储位置、属性或索引器中并将该值作为结果返回。 "

    我仍然不敢相信我不知道。

    【讨论】:

      【解决方案6】:

      ??是以下的语法糖:

      if(_user != null)
          return _user; // first part before ??
      else
          return (_user = GetUser() ); //Second part after ??
      

      编辑:

      正如@Rufus L 指出的那样:

      (_user = GetUser() );部分将GetUser的返回值赋值给_user,然后返回_user的值。如果我们简化前面的代码:

      if(_user != null)
          return _user;
      else
      {
          _user = GetUser();
          return _user;
      }
      

      额外信息:你可以链式赋值,只要类型相同,或者实现隐式转换:

      int x, y, z;
      x = y = z = 4;
      

      【讨论】:

      • 这解释了空合并运算符,但不是(_user = GetUser() ) 的作用(赋值并返回一个值)。
      • @Rufus L:你的权利,忘了那部分。现在已经添加了。
      【解决方案7】:

      它首先检查_user 是否不是null。如果不是 null 则返回它。否则,它将_user 设置为GetUser() 返回的任何值。

      伪代码

      _user != null 
          return _user 
      otherwise 
          _user = GetUser()
      

      这里有一个post 谈论“Null Coalescing operator”

      【讨论】:

      • 你的代码相当于 return _user ?? GetUser() 也可以工作,但效率较低,因为它没有设置 _user,因此在下次调用 getter 时,_user 仍然为空。
      • 实际上这段代码只有在_user不是null时才会返回一些东西(otherwise块只做一个赋值,但没有return语句)。
      猜你喜欢
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 2020-09-20
      • 2015-02-27
      • 2020-05-26
      • 2021-12-07
      相关资源
      最近更新 更多