【问题标题】:Usage of ?? operator (null-coalescing operator)的用法??运算符(空合并运算符)
【发布时间】:2013-09-13 17:12:34
【问题描述】:

我用 ??运算符在我的代码中非常重要。但是今天我刚刚遇到一个问题。

这是我用于的代码??运营商

private List<string> _names;
public List<string> Names
{
    get { return _names ?? (_names = new List<string>()); }
}

但在某些地方我也看到了这段代码。

private List<string> _names;
public List<string> Names
{
    get { return _names ?? new List<string>(); }
}

这些代码之间的真正区别是什么。在一个中,我正在分配 _names = new List(),而在另一个中,我只是在做 new List()。

【问题讨论】:

  • 这些是非常不同的,第二个可能是一个错误。
  • 为什么不直接初始化成员变量呢?代码会更干净。 private List&lt;string&gt; _names = new List&lt;string&gt;();.

标签: c# .net null-coalescing-operator


【解决方案1】:

我看到的唯一区别是,在第一种情况下,您的变量 _names 将包含一个新的空列表,而在第二种情况下则没有。在这两种情况下,返回的值都是相同的。

【讨论】:

  • 所以这意味着每次都会返回一个新列表,如果我调用Names.Add("SomeName"),然后调用Names.Count,我会得到0而不是1,对吧?跨度>
  • 没错,在第二种情况下。
【解决方案2】:

在第二种情况下,您没有将_names 分配给new List&lt;string&gt;(),如果_names 为空,则每次调用Names 时,它都会创建new List&lt;string&gt;(),但在第一种情况下,new List&lt;string&gt;() 会创建一个。

【讨论】:

  • 所以这意味着每次都会返回一个新列表,如果我调用Names.Add("SomeName"),然后调用Names.Count,我会得到0而不是1,对吧?跨度>
  • @FaisalHafeez 是的,但仅限于第二种情况
【解决方案3】:

在这两种情况下都会返回相同的值,但不同之处在于,如果您在私有函数中的任何位置访问 _names,则在第一种情况下,_names 将有一个空列表,而在第二种情况下则为空值。所以第一个实现按照编码标准是正确的,在第二种情况下你可能会遇到空异常的问题。

【讨论】:

    【解决方案4】:

    正如其他人所说,区别在于检索到属性后字段_names的状态。

    案例一

    get { return _names ?? (_names = new List<string>()); }
    

    如果_names 为空,将创建并分配一个新的List&lt;string&gt;。此后,每次检索属性 Names 都会返回刚刚创建的列表。

    案例 2

    get { return _names ?? new List<string>(); }
    

    如果_names 为空,将返回一个新的List&lt;string&gt;。与案例 1 相比,它不会被分配给任何东西。这意味着每次您检索Names 时,都会创建并返回一个新列表。


    话虽如此,您应该非常小心这段代码的两个版本。在get 中赋值不一定是件好事。懒惰地实例化属性值很方便,并且在您是唯一使用该类的人的情况下可能是可以接受的,但它的风格很差。您班级以外的任何用户都不会期望get 设置任何内容...这就是属性的set 部分的用途。从长远来看,您最好只返回_names 并在默认构造函数中实例化它。然后很清楚代码在做什么,并且您获得了保证的非空属性值。

    对于第二种情况,最好返回 null 并允许用户处理它。考虑以下情况,其中items 是一个大型对象集合,每个对象都包含您的属性Names,并且无论出于何种原因,Names 始终为空:

    foreach (var item in items.Where(x => x.Names != null)) {
        Console.WriteLine(String.Join(", ", item.Names));
    }
    

    如果您只是返回 null,则将跳过整个块。但是,由于您每次都返回一个新列表,因此您不仅要运行整个循环并且基本上什么都不做,而且每次迭代都会实例化一个新列表!在某些条件下,这可能会变得非常昂贵。

    【讨论】:

      猜你喜欢
      • 2012-09-19
      • 2011-02-13
      • 2011-03-16
      • 2015-03-27
      • 2023-03-23
      • 2012-09-23
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      相关资源
      最近更新 更多