代码之家  ›  专栏  ›  技术社区  ›  stevehipwell

如何在vb.net中实现值类型的“as”关键字?

  •  12
  • stevehipwell  · 技术社区  · 15 年前

    我们的大部分开发是在vb.net中完成的(不是我的选择),一个经常使用的代码模式使用“on error goto”,后跟“resume next”,这样所有数据库字段都可以用directcast()读取,任何dbnull值都会被忽略。

    当前代码为

    On Error GoTo error_code
    oObject.Name = DirectCast(oReader.Item("Name"), String)
    oObject.Value = DirectCast(oReader.Item("Value"), Integer)
    error_code:
    Resume Next
    

    C代码要替换此代码,启用删除错误代码将是

    oObject.Name = oReader["Name"] as string ?? string.Empty;
    oObject.Value = oReader["Value"] as int? ?? -1;
    

    问题在于,此C代码的vb.net eqivalent使用的Trycast()只能用于引用类型(可以为空的类型是值类型),而C as关键字可以用于引用和可以为空的类型。

    总之,是否有人有一个VB.NET代码的例子,它与每个数据库字段中一行的C代码做同样的事情?

    -编辑-

    我已经决定了在我们的案例中,我认为什么是最好的解决方案。helper方法不适合(由于管理原因),并且我们不能有扩展方法,因为我们只使用.NET 2.0(尽管使用vs 2008,所以我们得到if())

    oObject.Name = If(oReader.IsDBNull(oReader.GetOrdinal("Name")), String.Empty, oReader.GetString(oReader.GetOrdinal("Name")))
    oObject.Value = If(oReader.IsDBNull(oReader.GetOrdinal("Value")), 0, oReader.GetInt32(oReader.GetOrdinal("Value")))
    
    6 回复  |  直到 15 年前
        1
  •  5
  •   Jose Basilio    15 年前

    在Vb9.0中,“if”是一个真正的等同于c的合并操作??” 来源 MSDN :

    所以你可以使用:

    oObject.Name = IF(oReader.Item("Name").Equals(DBNull.Value),string.Empty,DirectCast(oReader.Item("Name"), String))
    
        2
  •  9
  •   Alex Essilfie    7 年前

    编辑

    不好意思,你这样胡说八道。我依靠一个 posting by Paul Vick (当时是VB团队的负责人)而不是 MSDN 而且没有安装Windows来测试代码。

    我仍然会留下我的帖子“严重修改(参考编辑历史来阅读错误的原文)”,因为我发现分数仍然有一些优点。

    因此,再次重申三点:

    1. 为了 引用类型 C·C as 由直接建模 TryCast 在VB中。

      但是,C为通过取消装箱处理值类型增加了一些额外的内容(即取消装箱值类型的可能性 Nullable 对应通路 作为 )

    2. VB 9提供了 If 操作人员 要实现两个不同的C运算符: null 聚结 ?? )有条件的( ?: )如下:

        ' Null coalescing: '
        Dim result = If(value_or_null, default_value)
    
        ' Conditional operator: '
        Dim result = If(condition, true_value, false_value)
    

    与前一个不同 IIf 函数这些是真正的短路运算符,即只执行必要的部分。尤其是,以下代码将编译并运行得很好 IIF 函数,因为我们可以除以零):

        Dim divisor = Integer.Parse(Console.ReadLine())
        Dim result = If(divisor = 0, -1, 1 \ divisor)
    
    1. 不使用VB6样式的错误处理( On Error GoTo … On Error Resume [Next] )。这是向后兼容的东西,便于vb6转换。相反,使用.NET的异常处理机制,就像在C中那样。
        3
  •  2
  •   Guffa    15 年前

    使用 IsDbNull 方法检查空值,而不是昂贵的Try-Fail handleFailure方法。错误处理几乎总是比在成为错误之前捕获条件更昂贵。

    (同样,错误处理应该使用异常,而不是错误时的vb6样式转到shell…)

    有条件的 If 像这样的一个函数:

    oObject.Name = If(oReader.IsDbNull(oReader.GetOrdinal("Name")), Nothing, oReader.GetString(oReader.GetOrdinal("Name")))
    

    我更愿意编写一些帮助器函数,这些函数可以使代码更可读、更高效:

    Function GetStringOrDefault(reader As DbDataReader, key As String) As String
       Dim ordinal = reader.GetOrdinal(key)
       If reader.IsDbNull(ordinal) Then
          Return Nothing
       Else
          Return reader.GetString(ordinal)
       End If
    End Function
    

    用途:

    oObject.Name = GetStringOrDefault(oReader, "Name")
    

    您也可以将它们作为 DbDataReader 类以使它们更具可读性。

        4
  •  1
  •   Cerebrus    15 年前

    我认为vb.net没有模拟 ?? C的运算符。但是,您可以使用C的三元运算符的等效值。- The IIF function 在你的情况下:

    公认的丑陋:

    oObject.Name = IIf(oReader.Item("Name").Equals(DBNull.Value), DirectCast(oReader.Item("Name"), String), String.Empty)
    oObject.Value = IIf(oReader.Item("Value").Equals(DBNull.Value), DirectCast(oReader.Item("Value"), Integer), -1)
    

    请务必阅读我上面提供的链接中的stephen weatherford的帖子,该链接建议使用一个从提供的参数推断类型要求的通用IIF函数。这是必要的,因为IIF函数总是返回一个对象!

    更好的选择是创建一个有条件地执行此强制转换的函数,而不是尝试在一行中执行。

        5
  •  1
  •   stevehipwell    14 年前

    每个人都在讨论中添加了一些有效的观点,所以我想我会总结一下重要的观点。

    1. vb.net trycast()是 不是 与关键字“c”相同。如果它是相同的,那么首先就不需要这个问题了。

    2. NET将if()函数用于三元运算和空合并运算。这不像C版本(?还有呢?尊重地)。请尝试避免使用vb.net iif()函数,因为这是不同的。

    3. 空合并代码模式不起作用,因为我们不能将Trycast()用于可为空的类型,因此我们必须使用terniary模式。

    4. oreader.is dbnull(oreader.getordinal(“name”))是检查值是否为dbnull的最佳方法。

        6
  •  0
  •   Paolo    15 年前

    根据文档,Trycast只适用于引用类型。不管怎样,使用idataReader的问题可能比Trycast更多。

    在循环IDataReader中的行之前,先获取列名称的序号值,然后使用强类型的getx方法来检索字段值,如so

    Dim name As Integer = oReader.GetOrdinal("Name")
    Dim value as Integer = oReader.GetOrdinal("Value")
    
    While reader.Read()
      oObject.Name = if(oReader.IsDbNull(name), string.Empty, oReader.GetString(name))
      oObject.Value = if(oReader.IsDbNull(value), -1, oReader.GetInt32(value)
    End While
    
    ' Call Close when done reading.
    oReader.Close()
    

    使用具有3个类似so参数的if运算符,可以使其像c三元布尔运算符eval那样工作?TrueExpression:错误表达式

    这将帮助您解决问题。