Evi*_*lDr 3 vb.net asp.net asp.net-4.5
假设我在webforms GridViewRow中有一个控件...
<asp:Literal ID="ltl_abc" runat="server" />
Run Code Online (Sandbox Code Playgroud)
在RowDataBound事件中,我可以使用以下任何方法访问控件.我一直以来一直使用DirectCast:
Protected Sub gv_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gv.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
' 1) Dim ltl_abc As Literal = DirectCast(e.Row.FindControl("ltl_abc"), Literal)
' 2) Dim ltl_abc As Literal = CType(e.Row.FindControl("ltl_abc"), Literal)
' 3) Dim ltl_abc As Literal = e.Row.FindControl("ltl_abc")
Run Code Online (Sandbox Code Playgroud)
使用任何特定方法有什么好处吗?我猜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)
Run Code Online (Sandbox Code Playgroud)
那么为什么开发人员应该投射(在这个例子中),或者这个例子过于简单?
对于您的情况,TryCast有一个IsNot Nothing检查可能会更加有利.
但是,要了解何时以及为何使用哪个,首先要看一下它们的MSDN定义.
介绍基于继承或实现的类型转换操作.... DirectCast 不使用Visual Basic运行时帮助程序进行转换 ...
返回将表达式显式转换为指定数据类型,对象,结构,类或接口的结果.
隐式转换不需要源代码中的任何特殊语法....显式转换使用类型转换关键字
介绍一种不会引发异常的类型转换操作.... 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)
Run Code Online (Sandbox Code Playgroud)
第一个例子有效,因为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)
Run Code Online (Sandbox Code Playgroud)
最后,隐式转换:
' 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
Run Code Online (Sandbox Code Playgroud)
这两个都有用,但请记住,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
Run Code Online (Sandbox Code Playgroud)
CType /隐式转换(编译相同):
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
Run Code Online (Sandbox Code Playgroud)
所以,基本上,由于.NET需要调用外部方法来确定转换对象需要做什么,CType/ implicit将运行得稍慢(这里的示例基准和示例).注意,因为它们都在MSIL中编译相同,CType并且隐式转换应该执行相同的操作.
那么你什么时候使用它们?我通常遵循一些简单的规则
DirectCastDim myInt = CInt("42").注意,这CType与IL中的编译方式相同TryCastDirectCast和/或Convert.ChangeType你也可以CType在那里使用第二个,但在我看来,如果我知道我正在转换为a Integer,那么我会选择更明确的CInt.Option Strict但是,如果你有,那么如果你将错误的东西传递给任何一个,你应该得到一个构建错误.
此外,虽然你可能会想一些替代TryCast的DirectCast有关重大分歧和使用的答案检查这太问题:为什么使用TryCast代替Directcast?
如果你注意到,那里我没有包含隐式输入.为什么?好吧,主要是因为我使用代码Option Strict On,并且在缩小类型时它并不真正允许隐式转换(请参阅"扩展和缩小转换").否则,就.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)
Run Code Online (Sandbox Code Playgroud)
还有一个:
' 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)
Run Code Online (Sandbox Code Playgroud)
因此,对于您的情况,它看起来像TryCast一个IsNot Nothing检查是要走的路.
| 归档时间: |
|
| 查看次数: |
2484 次 |
| 最近记录: |