我应该如何在VB.NET中将一个Object
转换为Integer
?
当我执行以下代码时:
Dim intMyInteger as Integer = TryCast(MyObject, Integer)
它说:
TryCast操作数必须是引用类型,但整数是值类型。
TryCast
等同于C#中的as
运算符。它是一种“安全转换”操作符,如果转换失败,不会抛出异常。相反,它返回Nothing
(在C#中为null
)。问题是,您不能将Nothing
(null
)(引用类型)赋值给Integer
(值类型)。没有Integer
null
/Nothing
这样的东西。
相反,您可以使用TypeOf
和Is
:
If TypeOf MyObject Is Integer Then
intMyInteger = DirectCast(MyObject, Integer)
Else
intMyInteger = 0
End If
这个测试用来检查MyObject
的运行时类型是否为Integer
。欲知详情请参见TypeOf
运算符的MSDN文档。
你也可以像这样写:
Dim myInt As Integer = If(TypeOf myObj Is Integer, DirectCast(myObj,Integer), 0)
此外,如果一个带有默认值(比如0)的整数类型不适合,你可以考虑使用 Nullable(Of Integer)
类型。
MyObject
是一个 Object
引用,它仍然可以指向任何类型的对象。If TypeOf x Is type
表达式 用于测试对象在运行时的类型。 - Jonathon ReinhartIif
是一个函数,已被 VB 2008 中的 If
运算符所取代。快速查看 MSDN 文档会有很大帮助。(我正在回答你的问题,但并不了解 Visual Basic。) - Jonathon ReinhartIIf
会失败(如果myObj不是整数,则会导致异常)。 IIf
始终评估真和假表达式,然后返回适当的表达式。 If(..)
的重点在于它仅评估一个表达式或另一个表达式。 在这种情况下,除非我们已经验证了我们有一个整数,否则它不执行DirectCast
。 在现代VB中,没有任何情况可以使用IIf(..)
是有益的; 所有使用它的地方都应该用If(..)
替换。 - ToolmakerSteveiif
与IIf
完全相同。由VB编译器根据需要转换大小写并匹配函数名称与现有函数签名。但您是正确的,IIf(..)
已经没有任何好处了,已被If(..)
取代 :) - ToolmakerSteveDim intMyInteger as Integer
Integer.TryParse(MyObject, intMyInteger)
使用 Directcast 并捕获 InvalidCastException 异常。
TryCast的等效方法是CType。如果可能,两者都会进行类型转换。相比之下,DirectCast仅在该类型已经存在时才会转换类型。
举个例子,您可以使用CType将字符串、短整型或双精度浮点数转换为整型。如果您尝试使用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
还有一种叫做可空类型的 null/Nothing 整数或任何其他静态类型,详情请参见 变量声明问号。但这并不意味着它是“引用”类型。
TryCast
不会尝试 CType
尝试的所有转换范围。它们的使用方式非常不同。TryCast
是一种非常严格(而且快速)的转换:它尝试“向上转换”到特定的子类。当需要将实例作为更通用的基类传递时使用它。CType
可以进行更多的转换——这既可以是好事也可以是坏事... - ToolmakerSteve
CInt
(或任何其他转换调用)与TryCast
/DirectCast
的目的不同。如果您有一个传入的数字值类型,例如Single或Double,并希望将其截断为整数,则可以使用它。将其应用于传入的“Object”意味着您不知道正在发生什么以及将尝试进行哪些转换工作。在我看来,这是一种冒险的编程风格。按照Jonathan所示的方法进行,必要时进行扩展。例如,如果您想要解析字符串,请检查其类型是否为字符串,然后调用TryParse。要明确。 - ToolmakerSteveINumeric
(或其他)接口。鉴于此,我们可以拥有一个传入的MyNumber As INumeric
而不是传入的MyObject As Object
。好的,现在我们知道了关于传入内容的"足够"信息,可以执行CInt(MyNumber)
,并且有信心知道将要完成的工作。 - ToolmakerSteve