对于您的情况,TryCast
与IsNot Nothing
检查可能会更加有利。
要理解何时以及为什么要使用它们,首先要看看它们的MSDN定义。
DirectCast
介绍了基于继承或实现的一个类型转换操作。 ... DirectCast 不使用Visual Basic运行时帮助程序转换 ...
CType
返回表达明确转换为结果指定的数据类型,对象,结构,类或接口。
Implicit Conversion
的隐式转换不需要在源代码中的任何特殊语法。 ...显式转换使用类型转换关键字
TryCast
介绍在不抛出异常的类型转换操作。 ... TryCast返回Nothing(Visual Basic),以便不必处理可能的异常,而只需对Nothing返回返回的结果。
去关闭这些定义中,我们可以假设CType
将基于给定System.Type
外部呼叫,而DirectCast
只需要使用下一个不同的名字现有的对象。同时,通过隐式转换,VB将尝试执行代码。 TryCast
,但是,将尝试把对象或只返回Nothing
(认为C#as
运营商)
例如:
' works
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s = DirectCast(obj, String)
' throws error: Unable to cast object of type 'System.Int32' to type 'System.String'.
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s = DirectCast(obj, String)
第一个示例,因为obj
已经是String
刚被定义为Object
。没有发生实际的转换。
现在让我们来看看CType
:
' works
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s = CType(obj, String)
' works - would prefer to use CStr() here instead, since it's more explicit (see below)
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s = CType(obj, String)
最后,隐式转换:
' works with Option Explicit. Throws build error with Option Strict: Option Strict On disallows implicit conversions from 'Object' to 'String'.
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s As String = obj
' same as above
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s As String = obj
这两个工作,但要记住,VB。NET这里调用一个独立的库做肮脏的工作:
DirectCast:
IL_0000: nop
IL_0001: ldstr "I'm a string!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: castclass [mscorlib]System.String
IL_000d: stloc.1
IL_000e: nop
IL_000f: ret
类型/隐式转换(编译相同):
IL_0000: nop
IL_0001: ldstr "I'm a string!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(object)
IL_000d: stloc.1
IL_000e: nop
IL_000f: ret
所以,基本上,由于.NET需要调用外部方法来确定它需要做什么来转换对象,因此CType
/隐式会运行得稍慢(example benchmarks and examples here)。请注意,由于它们都在MSIL中编译相同,所以CType
和隐式转换应该执行相同。
那么你什么时候使用它们?我一般遵循几个简单的规则
- 如果我知道(或希望)我的对象已经是我的目标类型,只是有不同的定义,我用
DirectCast
- 如果我的对象是不同类型的比我的目标类型,我使用适当的Convert方法。例如:
Dim myInt = CInt("42")
。请注意,这个编译一样CType
在IL
- 如果我不确定输入型的,我用
TryCast
- 如果我铸件/泛型转换,我将使用
DirectCast
和/或Convert.ChangeType
,根据上下文
您也可以使用CType
对于第二个那里,但在我看来,如果我知道我转换为Integer
,那么我会选择更明确CInt
。但是,如果你有Option Strict
,那么如果你把错误的东西传入任何一个,你都会得到一个构建错误。
此外,虽然你可能会想一些关于重大分歧的DirectCast
检查答案代TryCast
到这太问题及用途:Why use TryCast instead of Directcast?
如果你发现,我并没有包括在里面隐式类型。为什么?那么,主要是因为我使用Option Strict On
进行编码,并且它在缩小类型时不允许隐式转换(请参见"Widening and Narrowing Conversions")。否则,只要.NET而言,这几乎是相同的CType
好了,现在所有的这样做了,让我们来看看所有的三(四,我猜)与Control
对象:
' control is just defined as a regular control
Dim control As New Control
' Runtime Error: Unable to cast object of type 'System.Web.UI.Control' to type 'System.Web.UI.LiteralControl'
Dim literal_1 As LiteralControl = DirectCast(control, LiteralControl)
' Runtime Error: Unable to cast object of type 'System.Web.UI.Control' to type 'System.Web.UI.LiteralControl'
Dim literal_2 As LiteralControl = CType(control, LiteralControl)
' returns literal_3 -> Nothing
Dim literal_3 As LiteralControl = TryCast(control, LiteralControl)
还有一:
' control as a LiteralControl stored as a Control
Dim control As Control = New LiteralControl
' works
Dim literal_1 As LiteralControl = DirectCast(control, LiteralControl)
' works
Dim literal_2 As LiteralControl = CType(control, LiteralControl)
' works
Dim literal_3 As LiteralControl = TryCast(control, LiteralControl)
因此,对于您的情况,它看起来像TryCast
与IsNot Nothing
检查是要走的路。
** 3)**是否使用Option Strict? (这里不是一个VB.NET的人,但我认为这是一个推荐使用的东西。)因为如果不是这样,那么这个问题应该减少到“我应该使用Option Strict吗?”,这对于我来说是有问题的。 – millimoose
我用显式,根据MSDN暗示严格,是的,它的工作原理。但我认为这是因为该变量被宣布为** Literal ** – EvilDr
它甚至可以在控件不存在的情况下工作(直到您尝试为属性赋值时才抛出Null引用),'Dim fakeCtrl as Literal = e.Row.FindControl(“NotThere”)' – EvilDr