代码之家  ›  专栏  ›  技术社区  ›  csauve

C#相当于VB.NET的DirectCast?

  •  49
  • csauve  · 技术社区  · 14 年前

    C#是否具有与VB.NET的DirectCast等价的功能?

    我知道它有()强制类型转换和'as'关键字,但它们与CType和TryCast一致。

    要清楚的是,这些关键字做了以下几点;

    CType/()类型转换 :如果它已经是正确的类型,请强制转换它,否则请查找类型转换器并调用它。如果找不到类型转换器,则抛出InvalidCastException。

    TryCast/“as”关键字 :如果类型正确,则强制转换它,否则返回null。

    :如果它是正确的类型,则强制转换它,否则将引发InvalidCastException。

    在我解释了以上内容之后,一些人仍然回答说()是等价的,所以我将进一步阐述为什么这是不正确的。

    DirectCast只允许在继承树上进行缩小或扩大转换。它不支持跨不同分支的转换,如()所做的转换,即:

    C#-编译并运行:

    //This code uses a type converter to go across an inheritance tree
    double d = 10;
    int i = (int)d;
    

    VB.NET-这不编译

    'Direct cast can only go up or down a branch, never across to a different one.
    Dim d As Double = 10
    Dim i As Integer = DirectCast(d, Integer)
    

    在VB.NET中,与我的C代码等价的是CType:

    'This compiles and runs
    Dim d As Double = 10
    Dim i As Integer = CType(d, Integer)
    
    10 回复  |  直到 7 年前
        1
  •  14
  •   Peter Mortensen Abd Al-Kareem Attiya    7 年前

    static T DirectCast<T>(object o, Type type) where T : class
    {
        if (!(type.IsInstanceOfType(o)))
        {
            throw new ArgumentException();
        }
        T value = o as T;
        if (value == null && o != null)
        {
            throw new InvalidCastException();
        }
        return value;
    }
    

    或者,即使它与VB不同,也可以这样称呼它:

    static T DirectCast<T>(object o) where T : class
    {
        T value = o as T;
        if (value == null && o != null)
        {
            throw new InvalidCastException();
        }
        return value;
    }
    
        2
  •  8
  •   djv    9 年前

    :

    好的,这里有一个C方法,据说它基本上是 DirectCast 在VB.NET中没有。

    static T DirectCast<T>(object o) where T : class
    {
        T value = o as T;
        if (value == null && o != null)
        {
            throw new InvalidCastException();
        }
        return value;
    }
    

    1. where T : class 约束,哪个 直播 没有。
    2. System.Object --再说一次,不是真的 直播
    3. 它使用 as class 首先是约束);打电话会抛出一个错误 InvalidCastException 如果不起作用;为什么要使用 作为 ,只会抛出相同的异常,如果您 (T)o 开始的路线?

    这个方法真的可以重写,以提供与 直播 具体如下:

    static T DirectCast<T>(object o) {
        return (T)o;
    }
    

    DirectCast<int>(12.0) 真的会和 (int)(object)12.0 DirectCast<T> 这种方法完全没有必要。

    下面是一个例子 直播 () VB.NET和C#之间是否“不同”:

    VB语言:

    Dim i As Integer = 12
    Dim l As Long = DirectCast(i, Long) ' does not compile '
    

    C#:

    int i = 12;
    long l = i; // DOES compile
    

    这有什么意义 当你已经知道一个对象的类型时? 这不是一个现实的比较,因为在VB.NET中没有任何理由调用 直播 就像上面的代码一样(如果你想转换一个值 System.Int32 类型的值 System.Int64 在VB.NET中,您可以使用 CLng 直播 )如果有一个变量 在那里, 然后 直播

    VB语言:

    Dim i As Integer = 12
    Dim o As Object = i
    Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception '
    

    int i = 12;
    object o = i;
    long l = (long)o; // compiles, throws an exception
    

    所以我认为 直播 在VB.NET中,在任何实际使用它有意义的场景中(即,当编译时对象的类型未知时), 与直道相同 () .


    编辑 :好吧,我真遗憾发布了一些没有编译的VB代码。在重新考虑我说的话之后,我收回了我的话 第二 回答,但保持第一。

    直播 与C#的()类型相同:

    Dim o As Object = SomeObject()
    Dim i As Integer = DirectCast(o, Integer)
    

    C#:

    object o = SomeObject();
    int i = (int)o;
    

    这是因为,如果 o 键入为 系统对象 () o System.Double ,那么 (int)o o 作为一个整体解开包装 在它被转换成 系统.Int32 (如果你不相信我,你自己试试!)。


    注:以下不准确,因为 进行加宽转换;无论如何,我要留给子孙后代。

    另一方面,在处理加宽与缩小转换时,使用 () (int)someDouble ). 在这种情况下, 直播

    VB语言:

    Dim i As Integer = 12
    Dim l As Long = DirectCast(i, Long) ' does not compile, actually '
    

    int i = 12;
    long l = i;
    
        3
  •  1
  •   Eamon Nerbonne    14 年前

    您可以自己实现:

    static T CastTo<T>(this object obj) { return (T)obj; }
    

    可用性如下:

    3.5.CastTo<int>(); //throws InvalidCastException.
    

    这是可行的,并且不涉及用户定义的转换器,因为泛型在运行时被“解析”,而类型转换在编译时被解析-框架实际上不会为每个泛型生成不同的实现 T 而是分享了类似的实现

        4
  •  1
  •   Michael Buen    14 年前

    实际上,如果编译器推断类型化变量无法转换为其他类型,那么它只会捕获DirectCast冲突

    double d = 10;
    int i = (int)d;
    
    Dim d As Double = 10
    Dim i As Integer = d
    

    注意这个构造的危险性,当您在VB.NET中仅仅将double赋值给integer时,double会意外地缩小为integer。

    // will not compile, cannot convert double to int
    
    double d = 10;
    int i = d; 
    
    ' will not compile, cannot convert double to int
    
    Dim d As Double = 10
    Dim i As Integer = DirectCast(d, Integer) 
    

    [编辑]

    在C#中不需要使用DirectCast,运行时还可以防止长整型值的加载。这就是csauve所争论的,即C#没有DirectCast,DirectCast可以阻止分配不同类型的变量,而“因为”C#没有这个DirectCast,它将在分配不同类型时自动出错。但正如你所见,事实并非如此,C#的角色是 确切地 与DirectCast相同。这将导致 无效例外 运行时错误:

    long l = 10;
    object o = l;
    int i = (int)o;
    

    运行时错误 如上所述:

    Dim l As Long = 10
    Dim o As Object = l
    Dim i As Integer = DirectCast(o, Integer)
    

    现在,这就是“有趣”的部分,在VB.NET中,你必须记住许多关键字才能完成一些事情。在C语言中,如果一个给定的关键字可以在另一个场景中使用(比如在这个变量的向下转换中),他们不会发明另一个关键字来实现它。

    long l = 10;
    object o = l;
    int i = (int)(long)o;
    

    在VB.NET中,如果确实要向下转换变量,并希望采用正交方式进行转换,即只记住一个关键字,则必须执行以下操作:

     Dim l As Long = 10
     Dim o As Object = l
     Dim i As Integer = DirectCast(DirectCast(o, Long), Integer)
    

    但那是不会编译的,那么如何实现长到整数的向下转换呢?你必须记住VB.NET的其他关键字。而在C#中,它是正交的,可以使用这个构造来取消对变量的装箱 (typehere) ,也可以使用相同的构造进行向下/向上投射 (在此处键入)

     Dim l As Long = 10
     Dim o As Object = l
     Dim i As Integer = CType(o, Integer)
    

    隐马尔可夫模型。。我认为这种混乱源于对 ,首先用于向下投射;第二,同样的结构(检查这篇文章的第一部分, object o = l

    这是一个低沉的声音。。。

    long l = 1;
    int i = (int) l;
    

    …不等于:

    Dim l As Long = 1
    Dim i As Integer = DirectCast(l, Integer)
    

    如果要执行向下投射,必须执行以下操作:

    Dim l As Long = 1
    Dim i As Integer = CInt(l) ' can also use CType
    

    现在,如果一个VB.NET程序员是通过意图编程的,并且在编码时不困倦,那么当他完全意识到DirectCast不能分配不同的类型时,为什么他会使用DirectCast呢?如果VB.NET程序员真正想要的是向下转换,那么他首先就不应该尝试DirectCast。现在,VB.NET程序员在发现DirectCast不能用于向下转换时,必须将他编写的内容退格,并用CInt(或CType)替换它

        5
  •  1
  •   Wai Ha Lee captain-yossarian from Ukraine    5 年前

    VB.NET版本:

    Dim xxx as label = Directcast(sender, label)
    

    C#:

    label xxx = (label)sender;
    
        6
  •  0
  •   Michael Buen    14 年前

    关于。。。

    //This code uses a type converter to go across an inheritance tree
    string s = "10";
    int i = (int)s;
    

        7
  •  0
  •   Amry    14 年前

    让我试试这个。

    首先,让我澄清一下。这个 不会 编译:

    //This code uses a type converter to go across an inheritance tree
    string s = "10";
    int i = (int)s;
    

    VB的CType

    在VB中,可以使用:

    Dim s as String = "10"
    Dim i as Integer = CType(s, Integer)
    

    string s = "10";
    int i = Convert.ToInt32(s);
    

    VB的DirectCast

    如果它是正确的类型,则将其转换, 否则抛出一个 无效的例外。

    分支,永远不会跨越到另一个不同的地方 一个。

    从这个解释来看,这将是一个直接相当于C#演员阵容。但是,在C#中,您只需要为强制转换指定强制转换运算符。铸造是完全可选的。例子:

    // casting down
    object t = "some random string needing to be casted down";
    string s = (string) t;
    // casting up
    object a = s;
    // explicitly casting up although it's totally optional
    object b = (object) s;
    


    VB的TryCast

    您已经正确理解了这相当于C#as关键字。

        8
  •  0
  •   Michael Buen    14 年前

    我认为这个场景最好地概括了为什么DirectCast对非对象(object关键字)类型的编译时类型检查安全性有错误的感觉,并且只是为了退格。

    float f = 10;
    long l = f;
    
    Option Strict On    
    Dim f As Single = 10
    Dim l As Long = f
    

    C#编码器在发现float不能直接赋值给long并且不会编译时,将执行以下操作:

    long l = (long)f;
    

    这是正确的。

    Dim l As Long = DirectCast(f, Long)
    

    VB.Net程序员:“请让我做我的投标,请编译,请……”

    Dim l As Long = CLng(f)
    

    这就是我所说的DirectCast具有错误的编译时类型检查安全性。如果程序员不知道何时何地应该使用DirectCast,那么DirectCast就意味着要退格。DirectCast是一个安全毯 不是一直穿的。

    如果DirectCast最终不被使用,它在这种情况下有多有用?


    @朱尔斯

    我并不是说所有的VB.NET程序员都不知道DirectCast的真正用途是什么,他们中的一些人确实知道DirectCast只用于对象类型(以及装箱在对象中的基本类型)。

    有一种情况是,VB.NET程序员将现有的C代码重新编码到VB.NET中,会得出错误的结论,即预期(无论正确与否)语言之间是对称的。

    当他在代码中看到这个结构。。。

    TextBox txt = (TextBox)sender;
    

    Dim txt As TextBox = DirectCast(sender, TextBox)
    

    现在,因为我们程序员喜欢对称,我们中的一些人(如果我不知道CLng的话,我可能也会这样)会倾向于转换这些代码。。。

    /* numbers are stored in file as float(component's file structure 
    is designed by 3rd party company) */
    float f = file.ReadFloat(0); 
    long l = (long)f; // but we don't care about using the fractional part
    

    …对此:

    Dim f As Single = file.ReadFloat(0)
    Dim l As Long = DirectCast(f, Long)
    

    如果一个C#人将C#代码转换成VB.NET,他会因为这里明显缺乏对称性而感到沮丧。

    但是要避免VB.NET程序员犯错误地推断出第一个代码的意图。上面的C#代码片段 就这样开始了它的生活

    float f = file.ReadFloat(0); 
    long l = f; 
    

    不兼容的类型分配,与等效的VB.NET Option Strict On Option Strict 设置为 On ,过于宽大)。所以我们需要将float类型转换为long-use (long) . 变成这样: long l = (long)f;

    现在把一个变量类型转换成另一个兼容的类型,就像我们转换这段代码一样。。。

    …此代码:

    Dim txt As TextBox = DirectCast(sender, Textbox)
    

    我们必须转换这个代码。。。

    long l = (long)f; // will compile
    

    …此代码:

    Dim l As Long = DirectCast(f, Long) ' will not compile
    

    铸造

    在我看来,DirectCast应该被命名为 铸件

        9
  •  0
  •   Peter Mortensen Abd Al-Kareem Attiya    7 年前

    在C#中有两种类型的强制转换。如果没有额外的代码,就没有与C#中的DirectCast关键字等价的东西。如果你没有自己创建它,最接近的方法就是使用 () .

    您有:

    My_Object c = (My_Object)object
    

    My_Object c = object as My_Object
    

    在第二阶段, c

    What is the difference between explicit and implicit type casts?

        10
  •  0
  •   SSS    6 年前

    DirectCast () 不要总是生成相同的IL,所以我认为这是VB和C编译器之间的区别。

    AFAICT,引用类型使用 castclass IL指令,而对于值类型,编译器根据输入类型生成相关的IL。

    在C#中,从 double integer conv.i4

    有趣的是,如果你用一种中间物 object unbox 而不是试图进行转换。

        11
  •  -1
  •   Peter Mortensen Abd Al-Kareem Attiya    7 年前

    铸件应相同;它抛出了一个InvalidCastException。试试这个C#:

     string t = "hello";
     object x = t;
     int j = (int) x;