C#中检查空值对象的最佳语法是什么?

4

我总觉得写这样的东西很不对

if (MyObject)
    // do something

或者反过来
if (!MyObject)
    // do something

然而,你可以认为它比其他语言更简洁。
if (MyObject != null)
    // do something

if (MyObject == null)
    // do something

有没有任何非主观的理由来选择一个而不是另一个?
6个回答

37

C#中,你不能这样做

if (MyObject) 

为了检查 null,这是一个编译时错误(如果类没有隐式的布尔转换运算符)。

if (!MyObject)

如果类没有重载 operator ! 返回布尔值(或可以隐式转换为布尔值的值),则!obj也无效。

因此,您必须坚持使用obj == nullobj!= null

总之,非主观原因是能够编译您的代码!

更新(故事):

从前,在古老的C语言中,没有bool类型。零被认为是false,而每个非零值都被认为是true。您可以编写:

while(1) { }

创建一个无限循环。
你也可以做一些像这样的事情

int n  = 10;
while (n--) { }

需要循环执行n次。 这种策略存在的问题是:

int x = 10;
if (x = 0) { // bug: meant to be x == 0
}
你错过了一个字符,从而导致了一个错误(大多数现代C编译器都会在这个语句上发出警告,但它仍然是合法的C代码)。这就是为什么你会看到像这样的代码。
if (5 == variable) 

if (NULL == pObj)

在很多地方,因为它不容易出现上述错误,所以人们经常使用。

C# 的设计者决定要求 ifwhile 等条件语句中的条件表达式为布尔类型,并禁止将类型转换为布尔类型(除非它们明确声明了一个被强烈反对的重载运算符),以减少错误的可能性。因此,像这样的代码:

object x = null;
if (x) { }

int y = 10;
if (y) { }
while (y--) { }

在C语言中是有效的,但在C#中根本编译不了
这绝对不是风格或协议问题。


5

有没有任何客观的理由来选择一个而不是另一个?

事实上,(1)和(2)无法编译就足以成为不使用它们的客观原因。

因此,我们只剩下(3)和(4):

if (MyObject != null)
    // do something

if (MyObject == null)
    // do something

这取决于你是否想要在MyObject为空时执行某些操作(4),或者当MyObject不为空时执行某些操作(3)。显然这不是一种风格选择。 如果总是采用相同的“风格”,那么当你需要另一个条件时,你就不得不这样做:

    if (MyObject == null) // style policy
    {
        // nothing here
    }
    else
    {
        // do something
    }

这并不是我所称之为易读代码的标准。


2

在我看来,这种情况下有点啰嗦是一件好事情。如果您可以同时进行两个操作,那么这就是这种情况的情况,但实际上不可能,正如Mehrdad所指出的那样。在C#中,“隐式”空检查(即if (MyObject))甚至无法编译。

if (MyObject == null)
    // do something

然而,检查一个整数是否大于0的情况与此相似。这里有两个等效的选项(在C中可以编译和运行正常,但在C#中不可以,除非我弄错了),它们是:

if (myInt)
    // do something

并且

if (myInt > 0)
    // do something

在这里我总是选择第二个选项,纯粹是为了更清晰(它不会被误认为是布尔值!),虽然你经常会在代码中看到前者的“隐式”检查。


1
@Kirtan:这是从 C 语法中遗留下来的问题,你可能会意外地将 null 赋给 MyObject,而不是等于它(只使用单个 =)。在 C# 中不存在这种风险。 - Noldorin
2
不,它们并不等同。在C#中,你不能说if (myInt)。这不是风格和协议的问题。这是C#中的一个语义规则 - Mehrdad Afshari
@Mehrdad:是啊,我在想这可能是在哪里实现的?C# 2.0?VB.NET?我知道我以前在某个地方成功地做过这件事。 - Noldorin
在C#中,你不能使用"if (myInt)"这样的语句,但在C语言中可以,但在C#中不行。 - Lasse V. Karlsen
@Noldorin - 即使在C语言中,myIntmyInt > 0 并不等价:if (myInt) 相当于 if (myInt != 0) 而不是大于0。if (-1) { printf("hello"); } 将会打印 "hello"。 - Mehrdad Afshari
显示剩余9条评论

2

C#中,if语句需要一个布尔表达式。

因此,在您上面的示例中,使用if(myObject)测试null实际上是错误的。您需要执行更冗长的 if(myObject == null)


1

如果您只想在对象为null时设置一个默认值,则可以使用C# 3.0中的 ?? 运算符。

代码:

MyType _myObject
if (SomeObject==null)
  _myObject = defaultObjectValue
else
  _myObject = SomeObject

可以写成

_myObject = SomeObject ?? defaultObjectValue;

这基本上意味着,如果 SomeObject 存在,则使用它,如果不存在,则使用默认值。

?? 运算符也被称为 "合并运算符"。http://en.wikipedia.org/wiki/%3F%3F_Operator - ya23

1

这取决于个人喜好。在C#中,检查null通常使用以下语法 -

if (MyObject != null)
    //Do Something.

4
谁说的,为什么?以上纯属个人喜好,在C#中既不是标准,也没有技术上的理由来支持这一点(在C#中!)。 - Konrad Rudolph
2
这在C语言中可能是理想的,但在C#中大多数人都不赞成;你可以在自己的代码中使用它,但不要无缘无故地强制别人改变他们的逻辑。对我来说,那段代码的意思是:“如果null不等于某个东西”。但我已经知道null的值了,它就是null!为什么我要找出null是否发生了变化?我想知道的是“如果某个东西不等于null”-所以我这样做:if (MyObject != null)。 - configurator
这样编写布尔表达式会使其更难阅读(它不像句子那样在逻辑上流畅)。正如其他人所说,在C#中编写空值检查的这种风格毫无帮助。 - dss539

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