在C#中使用可空类型

9

我只是对人们的意见感兴趣。在使用C#中的可空类型时,测试null的最佳实践方法是什么:

bool isNull = (i == null);

或者

bool isNull = !i.HasValue;

同时,当对非空类型进行赋值时,情况如下:
long? i = 1;
long j = (long)i;

比之更好的:

long? i = 1;
long j = i.Value;
8个回答

15

我会使用这个:

long? i = 1;
...some code...
long j = i ?? 0;

这意味着,如果inull,那么将被赋值为0。


1
此外,如果您想为该值类型分配默认值(可能是0,也可能不是),您可以使用long j = i ?? default(long); - Lloyd Cotten
我对那个表单的问题在于,并非所有的开发人员会立即知道正在发生什么。 - Ed S.
非常酷 - 我之前还没有发现 ?? 运算符或 "default"。 - Sam Schutte
3
专业的 .net 程序员应该知道什么是空值合并运算符,就像我期望 C 开发人员知道位移操作符一样。不要在编码时针对那些还没学过某些东西的程序员去降低代码难度。 - mmcdole
我可能会这样做 - 但这取决于0是否是可接受的哨兵值。 - mackenir
1
通过将null转换为0,实际上是在隐藏异常。这可能是适当的,这取决于您是否可以假定默认值。另外,您是否应该使用??运算符并不是我的问题的一部分。 - Martin Brown

12

使用由C#团队专门为您实现的表单。如果有人反对,请告诉他们Anders说这是可以的。

我的意思是,为了给您带来良好的编程体验,在将可空类型集成到C#中进行了许多工作。

请注意,就性能而言,这两种形式都会编译成相同的IL代码,也就是:

int? i = 1;
bool isINull = i == null;
int j = (int)i;

在 C# 编译器处理后,它最终会变成这样:
int? i = 1;
bool isINull = !i.HasValue;
int j = i.Value;

8
我会始终使用(i==null)的形式,这样能表达你正在做什么。
至于第二个问题,我认为任意一种形式都可以。然而,我总是首先检查它是否为空,并采取适当的措施——可能将那个检查和行动封装在一个帮助方法中(通常只是设置一个默认值)。

4

我在实践中没有使用过可空类型,但是对于第二个问题,我建议使用j.GetValueOrDefault()。文档表明,如果值为null,则后者实际上会抛出InvalidOperationException异常。根据long?的显式转换运算符的内部实现,前者也可能会抛出异常。我建议使用GetValueOrDefault并适当处理null/默认情况。


1

我倾向于在两者中都使用第一个,因为随着它在生命周期后期需要得到支持,这些似乎更容易理解原始作者的意图。


1

打开了Reflector。 HasValue是一个布尔标志上的查找,当值改变时设置该标志。因此在循环方面,查找将比比较更快。

public Nullable(T value)
{
    this.value = value;
    this.hasValue = true;
}

private bool hasValue;

internal T value;

public bool HasValue
{
    get
    {
        return this.hasValue;
    }
}

你检查过比较编译成什么了吗?如果语法糖最终不是调用 HasValue,我会感到惊讶的。 - mackenir

0

它们是一样的,但我会在两种情况下使用前者版本,因为它在语言中更常见:与 null 的比较和类型转换。


0
通常我倾向于在这两种情况下选择第一种选项,因为它更加“原始”而不是面向对象的(这实际上是我们所追求的),但这并不那么重要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接