gpt4 book ai didi

asp.net - 为什么 Cast (CType/DirectCast) 控制与隐式转换不同

转载 作者:行者123 更新时间:2023-12-02 18:54:59 25 4
gpt4 key购买 nike

假设我在 webforms GridViewRow 中有一个控件...

<asp:Literal ID="ltl_abc" runat="server" />

在 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")

使用任何特定方法有什么优势吗?我猜 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)

为什么开发人员应该进行强制转换(在这个例子中),或者这个例子太简单了?

最佳答案

根据您的情况,带有 IsNot Nothing 检查的 TryCast 可能会更有利。

要了解何时以及为何使用哪个,首先查看它们的 MSDN 定义。

<强> DirectCast

Introduces a type conversion operation based on inheritance or implementation. ... DirectCast does not use the Visual Basic run-time helper routines for conversion...

<强> CType

Returns the result of explicitly converting an expression to a specified data type, object, structure, class, or interface.

<强> Implicit Conversion

An implicit conversion does not require any special syntax in the source code. ... An explicit conversion uses a type conversion keyword

<强> TryCast

Introduces a type conversion operation that does not throw an exception. ... TryCast returns Nothing (Visual Basic), so that instead of having to handle a possible exception, you need only test the returned result against 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 已经是刚刚定义为 ObjectString。没有发生实际的转换。

现在让我们看看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

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

因此,基本上,由于 .NET 需要调用外部方法来确定转换对象所需执行的操作,CType/implicit 的运行速度会稍慢 ( example benchmarks and examples here )。请注意,由于它们在 MSIL 中编译相同,CType 和隐式转换应该执行相同的操作。

那么你什么时候使用它们?我通常遵循一些简单的规则

  1. 如果我知道(或期望)我的对象已经是我的目标类型,只是定义不同,我会使用 DirectCast
  2. 如果我的对象与目标类型不同,我将使用适当的 Convert 方法。示例:Dim myInt = CInt("42")。请注意,这与 IL 中的 CType 的编译方式相同
  3. 如果我不确定传入类型,我会使用 TryCast
  4. 如果我使用泛型进行转换/转换,我将使用 DirectCast 和/或 Convert.ChangeType ,取决于上下文

您也可以使用 CType 作为第二个,但在我看来,如果我知道我要转换为 Integer,那么我会选择更明确的CInt。但是,如果您启用了 Option Strict,那么如果您将错误的内容传递给其中任何一个,则无论哪种方式您都应该收到构建错误。

此外,虽然您可能想尝试用 TryCast 替换 DirectCast,但请检查此问题关于主要差异和用途的答案: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)

因此,对于您的情况,看起来带有 IsNot Nothing 检查的 TryCast 是可行的方法。

关于asp.net - 为什么 Cast (CType/DirectCast) 控制与隐式转换不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20540769/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com