【问题标题】:Using null-coalescing as a replacement for try catch block使用 null-coalescing 作为 try catch 块的替代品
【发布时间】:2012-01-28 16:53:41
【问题描述】:

在尝试设置从Comments 中的数据库返回的NULL 值时,我为什么会得到一个无效的强制转换异常,它的类型是Int32

我正在尝试替换这个:

                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;
    }

我只想感谢所有回答或发布此问题的人,一切都非常有用。谢谢!

【问题讨论】:

  • Comments 是否定义为可为空?
  • 您的 cmets 是否真正存储为整数或文本/字符串/varchar..?还请显示您第一次声明 Comments 的位置是可空类型,只是好奇
  • 它是否作为 DBNull 返回?
  • 请检查更新。谢谢
  • 如果它已经存储为int?,为什么还要转换它?

标签: c# asp.net .net sql-server null-coalescing-operator


【解决方案1】:

当值为 null 时,您的 SQL 阅读器将返回 DBNull;没有从 DBNullint? 的转换,并且 null-coalescing 运算符不会将 DBNull.Value 识别为需要合并的东西。

编辑 3

(原始代码的另一个问题:如果“Comments”不为空但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 没有 cmets 时返回一个空列表或一个空引用,那么您可以避免这一切。

【讨论】:

    【解决方案2】:

    我想三元表达式是这里的方法

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

    您也可以先将sqlReader["Comments"] 的返回值存储在一个变量中以缩短表达式

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

    【讨论】:

    • 这是一个非常干净的解决方案。
    【解决方案3】:

    ?? 运算符检查null,但sqlReader["Comments"] 永远不会是null。它将是Int32DBNull。您可以将null 转换为Int32?,但不能对DBNull.Value 执行此操作。您可以改用sqlReader["Comments"] as Int32?,它检查结果是否可以转换为Int32,如果不能,则分配null

    【讨论】:

    • as 只能与引用类型一起使用。
    • 不,as 确实也适用于可空类型。我不知道这是一个新功能,但我可能弄错了。
    • 啊,每天都学点新东西。这不是一个新功能。引入可空类型时,as 和 is 运算符已扩展为支持可空类型。
    • 这很奇怪。你在哪里查到的?我也查了一下,在这个链接上找到了文档,它声称是 C#2.0 规范,并说 isas 运算符支持可空类型:download.microsoft.com/download/9/8/f/…
    • 那是我找到的文件,我想我看错了。看一下 20.8.5:“只有当已知 T 是引用类型(第 20.7 节)时,as 运算符才能与类型参数 T 一起用作右侧。”但是,从同一个文档中,请参阅 24.3.6:“as 运算符(第 7.9.10 节)被扩展为支持可为空的类型。在 e as T 形式的操作中,e 必须是表达式,而 T 必须是引用类型、已知为引用类型或可为空类型的类型参数。”我找到了第一个,但错过了第二个。
    【解决方案4】:

    该语句尝试在合并值之前执行强制转换。您需要添加括号。从您上面的示例来看,该字段看起来也是int 而不是int?

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

    【讨论】:

      猜你喜欢
      • 2019-12-04
      • 2016-12-26
      • 1970-01-01
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多