使用 ?? 运算符并处理空值

3

我从 SQL Server 2008 数据库返回一个标量值:

string reason = cmd.ExecuteScalar().ToString() ?? : "";

我希望确保如果返回null,则reason = ""而不是null。

在这一行上出现错误:

错误3 无效的表达式项“:”

如何解决?

编辑:

感谢您对冒号进行更改,现在我在同一行上收到此异常:

string reason = cmd.ExecuteScalar().ToString() ?? "";
System.NullReferenceException occurred
  Message="Object reference not set to an instance of an object."

1
如果结果为NULL,它仍然会引发异常,因此简单的解决方案是确保数据库中的值不为空。另一个简单的解决方案是确保存储在数据库中的值设置为String类型,这意味着如果它为空,它不会引发异常。在C#中,没有值的字符串是空字符串。字符串变量的默认值为null,如果在控制台窗口上显示,则为空字符串或null字符(因此不会打印任何内容)。 - Security Hound
请查看我的答案(特别是最后一部分)。 - canon
如果您现在收到一个“NullReferenceException”异常,那么这表明“cmd”是“null”。 - Jacob
7个回答

10

请尝试这个:

string reason = cmd.ExecuteScalar().ToString() ?? "";

但是:这仍然会失败,因为如果.ExecuteScalar()返回一个NULL值,你调用该NULL值的.ToString()方法时已经引发了空引用异常......

所以我想在这里 ?? 运算符确实不能帮助你...只能做“通常”的处理:

object result = cmd.ExecuteScalar();

if(result != null)
{  
   reason = result.ToString();
}
else
{
   reason = "(NULL value returned)";
}

2
string reason = (cmd.ExecuteScalar() ?? String.Empty).ToString(); 这样写可以吗?无论如何,因为你给出了唯一正确的答案,所以点赞+1...(或者至少在一分钟前是这样...) - Ry-
有些人提出了相同的问题,但是并没有意义。原始问题通过去掉“:”得到了解释,因此 OP 进行了编辑,使得大多数答案都无效了——这是一个目标变化的情况。我刚刚删除了我的回答,谁在给我点踩就随便他们怎么想吧! - cristobalito
@marc,你正确指出了一个缺陷,你正确指出“??”本身不能解决问题。然而,说你有“the 正确答案”是错误的,因为你并没有提供解决方案!你不同意吗? - Anthony Pegram
@Anthony Pegram:这个“解决方案”(只需显式检查从ExecuteScalar返回的值是否为!= null)似乎如此明显,以至于我之前没有添加它...... - marc_s
@marc_s:原始问题非常明显..只需快速搜索一下"??运算符"就能解决最初的语法问题,但你还费心回答了呢? - Coeffect
显示剩余2条评论

8

首先,在使用 ?? 运算符时,不应该有 : 符号。

其次,要想在这里实现你所尝试的操作而不出错,需要以不同的方式进行:

object objReason = cmd.ExecuteScalar();
string reason = objReason == null ? "" : objReason.ToString();

这段代码将检查你返回的值是否为null,如果是,第二行将把reason设置为空字符串,否则它将使用你返回的值。


5

ExecuteScalar() 返回的是可能为 nullobject,因此不应该调用 .ToString(),因为这可能会抛出异常。

string reason = Convert.ToString(cmd.ExecuteScalar());

这个操作的原因是Convert.ToString()方法会将null转换为string.Empty
或者,如果你非常喜欢使用??,可以这样写:
(cmd.ExecuteScalar() ?? (object)"").ToString();

具体来说,Convert.ToString(object obj)将把null转换为空字符串。Convert.ToString(null)实际上会返回null。 - Anthony Pegram

2
你对条件运算符进行了混淆,其语法如下所示:? 条件运算符
String x = condition ? valueIfConditionIsTrue : valueIfConditionIsFalse;

使用 ?? null-coalesce 运算符,其语法如下:

String x = possiblyNull ?? valueIfPossiblyNullIsNull;

所以,除了上述内容之外...这是你真正想要的部分:
String reason = (cmd.ExecuteScalar() ?? "").ToString();

这将解决您在使用ToString()时出现空引用异常的问题。

2

把冒号去掉就行了。

string reason = cmd.ExecuteScalar().ToString() ?? "";

如需参考,请查看MSDN页面


5
是的,但是如果.ExecuteScalar()返回NULL,这仍然会导致失败,因为你的.ToString()已经引起了Null Reference Exception。 - marc_s
当然可以,但是当时我回答的问题是“我该如何修复这个语法错误?” - Coeffect
@Mannimacro - 除非您的答案不正确。否则它只会生成不同的错误。 - Security Hound
@Ramhound:因此我说它修复了原帖提出的“语法错误”。我只是展示了如何格式化 ?? 运算符。从这个意义上说,它是正确的。 - Coeffect

2
使用空值合并运算符时,不需要使用冒号:
string reason = cmd.ExecuteScalar().ToString() ?? "";

正如其他人指出的那样,使用ToString()会导致NullReferenceException抛出...所以你不会在这里得到任何好处。你最好将其分成多行:

var result = cmd.ExecuteScalar();
string reason = result == null ? "" : result.ToString();

1

只需使用

string reason = cmd.ExecuteScalar() ??  "";

2
ExecuteScalar() 返回类型为 object。因此,您的方法会导致编译器错误,"无法隐式将类型 'object' 转换为 'string'。" - Anthony Pegram

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