Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 为什么强制转换(CType/DirectCast)控件与隐式转换_Asp.net_Vb.net_Asp.net 4.5 - Fatal编程技术网

Asp.net 为什么强制转换(CType/DirectCast)控件与隐式转换

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的讨论,更多关于是否需要强制转换的信息? 为清晰起见进行更

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

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