C# 使用null合并替换try-catch块

C# 使用null合并替换try-catch块,c#,asp.net,.net,sql-server,null-coalescing-operator,C#,Asp.net,.net,Sql Server,Null Coalescing Operator,为什么在尝试设置从Comments中的Int32类型的数据库返回的NULL值时会出现无效的强制转换异常 我正在尝试替换这个: try { objStreamItem.Comments = (Int32)sqlReader["Comments"]; if (objStreamItem.Comments > 0) {

为什么在尝试设置从
Comments
中的
Int32
类型的数据库返回的
NULL
值时会出现无效的强制转换异常

我正在尝试替换这个:

                try
                {
                    objStreamItem.Comments = (Int32)sqlReader["Comments"];
                    if (objStreamItem.Comments > 0) { 
                        listComments = Comment.GetAll(objStreamItem.Id);

                    }
                }
                catch (InvalidCastException)
                {
                    // Execute if "Comments" returns NULL
                    listComments = null;
                    objStreamItem.Comments = 0;
                }
为此:

Comments = ((Int32?)sqlReader["Comments"]) ?? 0
这两种情况是不同的,但你应该明白这一点。我没有使用try-catch块,而是试图用一种更优雅的方式来解决这个问题

谢谢

更新 它作为可为空的整数存储在数据库中

    public int? Comments
    {
        get;
        set;
    }

我只想感谢每一个回答这个问题的人,每一件事都是非常有益的。谢谢 该语句尝试在合并值之前执行强制转换。您需要添加括号。根据上面的示例判断,该字段似乎是
int
而不是
int?

Comments = (Int32)(sqlReader["Comments"] ?? 0);

当值为null时,SQL读取器返回
DBNull
;没有从
DBNull
int?
的转换,并且null合并运算符不将
DBNull.Value
识别为需要合并的内容

编辑3

(原始代码的另一个问题是:如果“Comments”为非null,但
GetAll()
抛出
InvalidCastException
,则假定“Comments”返回null)

正如hvd指出的,您可以将As运算符用于可为空的类型:

objStreamItem.Comments = sqlReader["Comments"] as int?;
listComments = (objStreamItem.Comments ?? 0) > 0 ? Comment.GetAll(objStreamItem.ID) : null;

但是,如果您只定义了
Comment.GetAll()
,当传递给它的ID没有注释时,返回一个空列表或一个空引用,您就可以避免所有这些问题。

操作符检查
null
,但是
sqlReader[“comments”]
永远不会是
null
。它要么是
Int32
,要么是
DBNull
。您可以将
null
强制转换为
Int32?
,但不能使用
DBNull.Value
执行此操作。您可以使用
sqlReader[“Comments”]作为Int32?
,它检查结果是否可以转换为
Int32
,如果不能转换,则分配
null

我想这里应该使用三元表达式

objStreamItem.Comments = sqlReader["Comments"] is DBNull ? 0 : (Int32)sqlReader["Comments"] ;
还可以先将
sqlReader[“Comments”]
的返回值存储在变量中,以缩短表达式

var comments = sqlReader["Comments"];
objStreamItem.Comments = comments is DBNull ? 0 : (Int32)comments;

Comments
是否定义为可空?您的注释是否真正存储为整数或text/string/varchar。。?另外,请显示您第一次声明注释的位置。它的类型是否为nullable?是否作为DBNull返回?请检查更新。谢谢如果它已经存储为
int?
,为什么需要将其强制转换为
as
只能用于引用类型。不,
as
也确实适用于可空类型。我不知道这是一个新功能,但我可能弄错了。啊,每天都学些新东西。这不是一个新功能;当引入可空类型时,as和is运算符被扩展以支持可空类型。这很奇怪。你在哪里查到的?我也查了一下,在这个链接上找到了这个文档,它声称是一个C#2.0规范,并说
,因为
操作符支持可空类型:这是我找到的文档,我想我读错了。查看20.8.5:“仅当已知T为参考类型时,as运算符才能与类型参数T一起用作右侧(§20.7)。”但是,从同一文件中,请参见24.3.6:“as运算符(§7.9.10)扩展以支持可空类型。在形式为e的操作中,e必须是表达式,T必须是引用类型、已知为引用类型的类型参数或可空类型。“我找到了第一个,但错过了第二个。这是一个非常干净的解决方案。