用法??运算符(null-coalescing operator)

时间:2013-09-10 05:36:13

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

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

这里我用的代码是什么?操作

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()而在其他我正在做新的List()。

4 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

在第二种情况下,如果_names为空,则不会将new List<string>()分配给_names,每次拨打Names时,它都会创建new List<string>(),但是第一个案例new List<string>()创建一个。

答案 2 :(得分:2)

它会在两种情况下返回相同的值,但不同之处在于,如果您在私有函数中的任何位置访问_names,则_names在第一种情况下将具有空列表,但在第二种情况下将为空值。因此,根据编码标准,第一个实现是正确的,在第二种情况下,您可能会面临零异常问题。

答案 3 :(得分:2)

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

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

如果_names为空,则会创建并分配新的List<string>。在此之后,对属性Names的每次检索都将返回刚刚创建的列表。

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

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


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

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

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

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