用法 ??运算符(零合并运算符)
本文关键字:运算符 合并 用法 | 更新日期: 2023-09-27 18:30:48
我在代码中大量使用 ?? 运算符。但是今天我刚刚遇到了一个问题。
这里是我用于??运算符
的代码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()。
我看到的唯一区别是,在第一种情况下,您的变量_names将包含一个新的空列表,而在第二种情况下则不包含。在这两种情况下,返回的值将是相同的。
在第二种情况下,您不会为_names
分配new List<string>()
,如果_names
为null,则每次调用Names
时都会创建new List<string>()
,但在第一种情况下new List<string>()
创建。
它在两种情况下都会返回相同的值,但不同之处在于,如果您在私有函数中的任何位置访问_names_names在第一种情况下将有一个空列表,但在第二种情况下将具有空值。因此,根据编码标准,第一个实现是正确的,在第二种情况下,您可能会遇到空异常问题。
正如其他人所说,区别在于检索属性后字段_names
的状态。
案例1
get { return _names ?? (_names = new List<string>()); }
如果_names
为 null,则将创建并分配新的List<string>
。 在此之后,每次检索属性Names
都将返回刚刚创建的列表。
案例2
get { return _names ?? new List<string>(); }
如果_names
为 null,则将返回新的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,则将跳过整个块。 但是,由于您每次都返回一个新列表,因此您不仅要运行整个循环并且基本上什么都不做,而且要在每次迭代中实例化一个新列表! 在某些情况下,这可能会变得非常昂贵。