【问题标题】:How to cast from Object to Integer in VB.NET?如何在 VB.NET 中将对象转换为整数?
【发布时间】:2012-10-20 12:18:27
【问题描述】:

我应该如何在 VB.NET 中将 Object 转换为 Integer

当我这样做时:

Dim intMyInteger as Integer = TryCast(MyObject, Integer)

上面写着:

TryCast 操作数必须是引用类型,但 Integer 是值类型。

【问题讨论】:

  • 为什么不这样:CInt(MyObject)
  • @Dave - 在 Abacus 的回答中阅读我的 cmets。 Cint(或任何其他 conversion 调用)的目的与 TryCast/DirectCast 不同。如果你有一个传入的 numeric 值类型是明智的,例如Single 或 Double,并希望将其截断为整数。将其应用于传入的Object 意味着您不知道传入的内容以及将尝试进行哪些转换工作。恕我直言,这是一种冒险的编程风格。做 Jonathan 展示的事情,如有必要,可以扩展它。例如,如果你想要解析一个字符串,然后检查它的类型是否是字符串,然后调用 TryParse。明确。
  • @Dave ...希望 .Net 最终会支持 Numeric。例如。让所有数值类型都支持INumeric(或其他)接口。鉴于此,而不是传入MyObject As Object 可以传入MyNumber As INumeric。好的,现在我们对即将到来的内容“足够”了解,可以去做CInt(MyNumber),并且确信我们知道将要完成哪些工作。
  • 以免有人认为我建议避免使用转换运算符,我特意将它们应用于Object。我认为这是一种“代码味道”。我建议在您确定某些接口或基类之前不要使用转换运算符 - 这样您就可以知道您要求完成什么以及可能出现的问题。知道您是要求进行字符串解析,还是数字截断,或者仅仅是“拆箱”。

标签: vb.net string casting integer


【解决方案1】:

TryCast 相当于 C# 的 as 运算符。它是一个“安全转换”运算符,如果转换失败,它不会抛出异常。相反,它返回Nothing(C# 中的null)。问题是,您不能将Nothing (null)(引用类型)分配给Integer(值类型)。没有 Integer null/Nothing 这样的东西。

相反,您可以使用TypeOfIs

If TypeOf MyObject Is Integer Then
    intMyInteger = DirectCast(MyObject, Integer)
Else
    intMyInteger = 0
End If

这将测试MyObject运行时类型 是否为Integer。有关详细信息,请参阅MSDN documentation on the TypeOf operator

你也可以这样写:

Dim myInt As Integer = If(TypeOf myObj Is Integer, DirectCast(myObj,Integer), 0)

此外,如果一个具有默认值(如 0)的整数不适合,您可以考虑使用Nullable(Of Integer) 类型。

【讨论】:

  • 为什么MyObject的类型是Integer,而我们已经知道它是Object
  • 我们还不知道。我们只知道MyObjectObject reference。它仍然可以指向任何类型的对象。 If TypeOf x Is type expression 测试对象的运行时类型。
  • 你的这个声明不应该是iif而不是ifIf(TypeOf myObj Is Integer, DirectCast(myObj,Integer), 0)
  • 小写,它们没有任何意义。 Iif 是一个函数,在 VB 2008 中已被 If 运算符取代。快速浏览 MSDN 文档会有很长的路要走。 (我正在回答你的问题,但我什至不懂 Visual Basic。)
  • 除了从 String "1" 到整数 1 之外,不是强制转换。这是一个转换(字符串被解析)。 OP 专门询问 casting Object 引用,他假设该引用是整数到整数值。我会很感激那些代表点,谢谢。
【解决方案2】:

你可以用这个:

Dim intMyInteger as Integer

Integer.TryParse(MyObject, intMyInteger)

【讨论】:

  • 不,这是对 与 OP 提出的问题不同的回答,OP 提出的问题两年前已成功回答。首先,观察 Integer.TryParse() 不接受 Object 作为其第一个参数。它仅适用于 String。这应该是您的第一个线索,即 OP 关于 casting 的问题与 parsing 不同。
  • String 继承自 Object,这个答案是有效的。这是2年前成功回答的OP问题的另一个答案。此选项有一个好处,如果对象包含字符串格式的整数值,则成功的答案将不起作用,但此答案会。另一方面,我的回答需要装箱和拆箱,所以这是不利的一面。
【解决方案3】:

使用 Directcast 并捕获 InvalidCastException

【讨论】:

  • +1:乍一看,我认为这不是一个好的选择,因为异常在 .Net 中非常昂贵。但是,OP 确实声明他期望对象中有一个整数;如果它确实总是(或几乎总是)一个整数,那么执行 DirectCast 是非常有意义的,并且只捕获(罕见的)异常。虽然我个人使用 Jonathan 的风格,但我已经接受了多年的 .Net 使用培训,以避免出现“太贵”的例外情况。即使在他们不是的情况下。
【解决方案4】:

TryCast 的等效项是 CType。如果可能,两者都会进行类型转换。相比之下,DirectCast 只会在它该类型的情况下转换该类型。

为了说明,您可以使用 CType 将 String、Short 或 Double 转换为 Integer。如果你这样做,DirectCast 通常会给你一个语法/编译错误;但是如果您尝试使用类型 Object 来绕过错误(这称为“装箱”和“拆箱”),它将在运行时抛出异常。

    Dim OnePointTwo As Object = "1.2"
    Try
        Dim temp = CType(OnePointTwo, Integer)
        Console.WriteLine("CType converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    Catch ex As Exception
        Console.WriteLine("CType threw exception")
    End Try
    Try
        Dim temp = DirectCast(OnePointTwo, Integer)
        Console.WriteLine("DirectCast converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    Catch ex As Exception
        Console.WriteLine("DirectCast threw exception")
    End Try

这将输出:

    CType converted to: 1 (type: System.Int32)
    DirectCast threw exception

所以为了最严格地遵循 TryCast 语义,我建议使用这样的函数:

Shared Function TryCastInteger(value As Object) As Integer?
    Try
        If IsNumeric(value) Then
            Return CType(value, Integer)
        Else
            Return Nothing
        End If
    Catch ex As Exception
        Return Nothing
    End Try
End Function

并说明其效果:

Shared Sub TestTryCastInteger()
    Dim temp As Integer?

    Dim OnePointTwo As Object = "1.2"
    temp = TryCastInteger(OnePointTwo)
    If temp Is Nothing Then
        Console.WriteLine("Could not convert to Integer")
    Else
        Console.WriteLine("TryCastInteger converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    End If

    Dim NotANumber As Object = "bob's your uncle"
    temp = TryCastInteger(NotANumber)
    If temp Is Nothing Then
        Console.WriteLine("Could not convert to Integer")
    Else
        Console.WriteLine("TryCastInteger converted to: " & temp.ToString & " (type: " & temp.GetType.ToString & ")")
    End If
End Sub

运行 TestTryCastInteger() 将输出:

    TryCastInteger converted to: 1 (type: System.Int32)
    Could not convert to Integer

还有 is 诸如 null/Nothing Integer 或任何其他静态类型,称为“可空”类型,请参阅 Variable declaration question mark 了解更多信息信息。但这也不能真正使它成为“参考”类型。

【讨论】:

  • -1 表示“与 TryCast 等效的是 CType”。并不真地。使用 TryCast 的全部意义在于避免在运行时产生异常的可能性。如果转换失败,CType 导致异常。此外,TryCast 不会尝试CType 尝试的所有转换。两者的用法完全不同。 TryCast 是一个非常严格(且快速)的转换:它尝试“向上​​转换”到特定的子类。当需要将实例作为更通用的基类传递时使用它。 CType 可以进行更多的转换——这是好是坏..
  • .. 取决于程序员的意图。它可能会尝试更昂贵的转换,例如解析字符串。它的行为也可以在自定义类中重载,以执行任何操作。但除此之外,在这里推荐它的问题是,您没有足够的信息来了解 OP 的想法。这是一个有风险的建议,可能会导致细微的错误。它真的不应该用于从“对象”转换,除非程序员根本不关心传入的内容以及结果将是什么——他们只是“希望它工作”。旧的、不可靠的基本编程方式。
  • 总之,乔纳森是正确的,如果一个人的目标是编写一个可靠的程序。如果一个人无法控制传入的类型,并且卡在Object 声明中,而您期待value 类型,那么安全的继续方法是开始测试对象的类型。一旦你知道你有什么类型的对象,就决定做什么。
猜你喜欢
  • 2021-11-11
  • 2021-12-06
  • 1970-01-01
  • 2023-02-10
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多