是否有一种简写方法来返回可能为null的值?

Err*_*ain 61 c# null-coalescing-operator null-coalescing

如何编写以下方案的简写?

get
{
    if (_rows == null)
    {
        _rows = new List<Row>();
    }

    return _rows;
}
Run Code Online (Sandbox Code Playgroud)

Zei*_*kki 81

使用null-coalescing运算符(??):

get 
{ 
     _rows = _rows ?? new List<Row>(); 
     return _rows; 
}
Run Code Online (Sandbox Code Playgroud)

或(不太可读):

get { return _rows ?? (_rows = new List<Row>()); }
Run Code Online (Sandbox Code Playgroud)

?? ?? operator被称为null-coalescing运算符.如果操作数不为null,则返回左侧操作数; 否则它返回右手操作数.

  • return _rows ?? (_rows = new List <Row>()); (20认同)
  • @hvd OP想要一个*速记*,这正是这个答案所提供的. (19认同)
  • @hvd提供的文件?? ?? 不仅清楚.用我自己的话来说,我看不出有必要改写**明确的**文档. (12认同)
  • 好吧,我认为在这种情况下它仍然具有可读性,如果你知道`??`运算符,理解它应该不是问题. (6认同)
  • @hvd所以你不喜欢`??`?就可读性而言,这不是讨论此功能是否有用的地方. (5认同)
  • @maaartinus一个明显的维护问题是当您需要扩展函数以将字段初始化为无法在单个表达式中写入的内容时.你不能.您需要先将其转换回OP首先使用的内容. (2认同)

Rom*_*ner 41

这是懒惰的初始化模式,因此直接的方法是使用Lazy <T>类.

class Foo
{
    Lazy<List<Row>> _rows;

    public Foo()
    {
        _rows = new Lazy(() => new List<Row>());
    }

    public List<Row> Rows
    {
        get { return _rows.Value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

这具有额外的优点,即它不会用初始化逻辑"污染"吸气剂.

  • 我选择了他在问题中使用的OP.我假设这只是一个例子,实际对象更重. (3认同)

Dmi*_*nko 20

我建议三元运算符

get {
  return _rows == null ? _rows = new List<Row>() : _rows;
}
Run Code Online (Sandbox Code Playgroud)

或者因为空List<Row>没有带来太大的开销,为什么不摆脱显式_row字段并实现只读属性(C#6.0语法):

public IList<Row> Rows {get;} = new List<Row>();
Run Code Online (Sandbox Code Playgroud)

  • C#6解决方案是可行的方法. (5认同)

jpm*_*c26 18

这是一个更好的主意:防止_rows永远存在null.

使您的构造函数初始化变量:

public MyClass()
{
    this._rows = new List<Row>();
}
Run Code Online (Sandbox Code Playgroud)

然后你的财产就是

get
{
    return this._rows;
}
Run Code Online (Sandbox Code Playgroud)

确保如果需要"清除"变量,则始终调用其Clear方法或分配新的空列表而不是分配null.如果您真的需要在整个班级中使其清晰且一致,则可能在方法中对该操作进行编码.

这是很多更符合逻辑.如果你的变量永远不应该null,那就永远不应该null.它还巧妙地避免了条件和具有getter修改状态的问题.

  • 在像这里的空列表的情况下,没有太大的区别.但是,总的来说并非总是如此.如果对象的初始化需要更长时间,并且您(作为库的作者)不确定它是否曾被调用程序请求,该怎么办?然后这个方法会引入太多的开销,延迟加载是要走的路. (3认同)

Sin*_*atr 12

List<Row> _rows;
public List<Row> Rows => _rows ?? (_rows = new List<Row>());
Run Code Online (Sandbox Code Playgroud)


Ric*_*ett 10

正如其他人所说,您可以在此方案中使用null-coalescing运算符.

get
{
    return _rows ?? (_rows = new List<Row>());
}
Run Code Online (Sandbox Code Playgroud)

值得注意的是,这是ReSharper建议的那种变化(他们称之为快速修复).

在你的例子中,它将在if声明下放置一个小的波形.将鼠标悬停在它上面会显示出如何更改/简化代码的建议.

转换成 '??'  表达

稍后点击几下,即可实施更改.

在此输入图像描述


eoc*_*ron 5

像这样例如:

get{ return _rows ?? (_rows = new List<Row>()); }
Run Code Online (Sandbox Code Playgroud)


Dmi*_*nko 1

return _rows ?? (_rows = new List<Row>());
Run Code Online (Sandbox Code Playgroud)

  • 或者更短: return _rows == null?新列表&lt;行&gt;:_rows (3认同)
  • @nosbor 这两个都继续返回列表的新实例,因为它们使 _rows 未分配,这与OP要求的行为不同。 (3认同)