Asp.net 为什么强制转换(CType/DirectCast)控件与隐式转换
假设我在webforms GridViewRow中有一个控件Asp.net 为什么强制转换(CType/DirectCast)控件与隐式转换,asp.net,vb.net,asp.net-4.5,Asp.net,Vb.net,Asp.net 4.5,假设我在webforms GridViewRow中有一个控件 <asp:Literal ID="ltl_abc" runat="server" /> 使用任何特定的方法有什么好处吗?我想DirectCast的效率稍微高一点,但可能容易出错,但隐式强制转换是否存在任何危险(选项3) 从历史上看,我从未见过任何错误,直到我尝试为控件的属性指定一个值,这让我觉得第一步并不是那么重要 请注意,这并不是DirectCast与CType的讨论,更多关于是否需要强制转换的信息? 为清晰起见进行更
<asp:Literal ID="ltl_abc" runat="server" />
使用任何特定的方法有什么好处吗?我想DirectCast的效率稍微高一点,但可能容易出错,但隐式强制转换是否存在任何危险(选项3)
从历史上看,我从未见过任何错误,直到我尝试为控件的属性指定一个值,这让我觉得第一步并不是那么重要
请注意,这并不是DirectCast与CType的讨论,更多关于是否需要强制转换的信息?
为清晰起见进行更新
Protected Sub gv_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gv.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
' This works fine, but no explicit casting is done:
Dim ltl_abc As Literal = e.Row.FindControl("ltl_abc") ' no (explicit) cast
ltl_abc.Text = "Hello World"
' This also works until I try to access the object's properties
Dim ltl_abc As Literal = DirectCast(e.Row.FindControl("NonExistentId"), Literal)
因此,开发人员为什么要进行强制转换(在本例中),或者本例太简单了?您可能希望在此处查看答案: 您的问题可以归结为DirectCast与CType 至于为什么不应该使用隐式强制转换,您已经指出了问题中的一些缺点(即,如果找不到,则有效等)。
DirectCast()
是最有效和最快速的,但当目标不是您要查找的类型或为空时,将引发异常
TryCast()
(您没有列出)与DirectCast()
基本相同,但从不抛出异常,而是返回null
CType()
效率较低,只有在目标对象和目标对象类型之间没有转换可用时才会引发异常。如果存在转换,则它将运行该转换,如果目标为空,则该转换可能会失败
Explicit不会自动为您执行转换,如果类型不完全匹配(即,将数组分配给IEnumerable变量),则不会引发异常,如果目标为null,则不会引发异常。因此,在以后尝试访问该对象时,可能会出现异常。因此,它非常接近于TryCast()
,而不存在将对象分配给兼容对象的问题
对于您的示例,我建议使用带有一些异常处理的
DirectCast()
对于您的情况,TryCast
和isnothing
检查可能更有益
但是,要理解何时以及为什么要使用它,首先要看一下它们的MSDN定义
介绍基于继承或实现的类型转换操作。。。DirectCast不使用Visual Basic运行时帮助程序例程进行转换
返回将表达式显式转换为指定数据类型、对象、结构、类或接口的结果
隐式转换不需要源代码中的任何特殊语法。。。显式转换使用类型转换关键字
引入不引发异常的类型转换操作。。。TryCast不返回任何内容(VisualBasic),因此不必处理可能的异常,只需根据任何内容测试返回的结果
根据这些定义,我们可以假设CType
将基于给定的System.Type
进行外部调用,而DirectCast
将仅使用不同名字对象下的现有对象。同时,通过隐式转换,VB只会尝试执行代码<但是,code>TryCast将尝试强制转换对象,或者只返回Nothing
(将C#视为
操作符)
例如:
' 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
已经是一个字符串
,它刚刚被定义为对象
。没有发生实际的转换
现在让我们看一下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
CType/隐式转换(编译相同的代码):
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
/implicit将运行得稍慢()。注意,由于它们在MSIL中编译相同,CType
和隐式转换的执行应该相同
那你什么时候用?我通常遵循几个简单的规则
DirectCast
Dim myInt=CInt(“42”)
。注意,这与IL中的CType
编译方式相同TryCast
DirectCast
和/或,具体取决于上下文CType
作为第二个变量,但在我看来,如果我知道我正在转换为Integer
,那么我将选择更明确的CInt
。但是,如果您启用了选项Strict
,那么如果您将错误的内容传递到任何一种方式,您都会得到一个构建错误
此外,虽然您可能想尝试用TryCast
替换DirectCast
,但请检查有关主要差异和用途的问题的答案:
如果您注意到,我没有在其中包含隐式键入。为什么?主要是因为我使用选项对
进行了严格的编码,并且在缩小类型时它实际上不允许隐式转换(请参阅)。否则,就.NET而言,它与CType
好了,现在所有这些都完成了,我们上厕所吧
' 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)