C#'s equivalent to VB.NET's DirectCast?
C是否与VB.NET的DirectCast等效?
我知道它有()强制转换和"as"关键字,但这些都符合ctype和trycast。
为了清楚起见,这些关键字做了以下的工作:
ctype/()强制转换:如果它已经是正确的类型,则强制转换它,否则查找类型转换器并调用它。如果找不到类型转换器,则引发InvalidcastException。
trycast/"as"关键字:如果类型正确,则强制转换,否则返回空值。
DirectCast:如果是正确的类型,则强制转换它,否则将引发InvalidCastException。
在我阐述了以上内容之后,一些人仍然回答说()是等价的,所以我将进一步阐述为什么这不是真的。
DirectCast只允许缩小或扩大继承树上的转换。它不支持跨不同分支的转换,如(),即:
C-这编译并运行:
1 2 3 | //This code uses a type converter to go across an inheritance tree double d = 10; int i = (int)d; |
vb.net-这不编译
1 2 3 | '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:
1 2 3 | 'This compiles and runs Dim d As Double = 10 Dim i As Integer = CType(d, Integer) |
它看来,清澈的功能性,这是你想要的不是在C #。。。。。。。虽然这个吧………………… </P >
1 2 3 4 5 6 7 8 9 10 11 12 13 |
或,虽然这是不同的从VB呼叫它的类: </P >
1 2 3 4 5 6 7 8 9 | static T DirectCast<T>(object o) where T : class { T value = o as T; if (value == null && o != null) { throw new InvalidCastException(); } return value; } |
第二次更新:
好的,这里有一个C方法,它被提议基本上像
1 2 3 4 5 6 7 8 9 | 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 2 3 | static T DirectCast<T>(object o) { return (T)o; } |
有趣的观察:实际上,这个方法所要做的就是装箱一个值,然后尝试取消装箱。换句话说,
下面是一个例子,说明vb.net和c之间,
VB:
1 2 | Dim i As Integer = 12 Dim l As Long = DirectCast(i, Long) ' does not compile ' |
C:
1 2 | int i = 12; long l = i; // DOES compile |
好的,所以一个编译,另一个不编译。但是看看代码。当你已经知道一个对象的类型时,
VB:
1 2 3 | Dim i As Integer = 12 Dim o As Object = i Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception ' |
C:
1 2 3 | int i = 12; object o = i; long l = (long)o; // compiles, throws an exception |
因此,我认为,在vb.net中,在任何实际使用它有意义的场景中(即,在编译时不知道对象类型时),
编辑:好吧,我很遗憾发布了一些没有编译的VB代码。在重新考虑了我所说的话之后,我收回了我的第二个答案,但保留了第一个。
如果您所指的是
VB:
1 2 | Dim o As Object = SomeObject() Dim i As Integer = DirectCast(o, Integer) |
C:
1 2 | object o = SomeObject(); int i = (int)o; |
这是因为,如果
注意:下面的内容不准确,因为
另一方面,在处理加宽和变窄转换时,使用c中的
VB:
1 2 | Dim i As Integer = 12 Dim l As Long = DirectCast(i, Long) ' does not compile, actually ' |
C:
1 2 | int i = 12; long l = i; |
您可以自己实现它:
1 | static T CastTo<T>(this object obj) { return (T)obj; } |
可用性如下:
1 | 3.5.CastTo<int>(); //throws InvalidCastException. |
这是可行的,并且不涉及用户定义的转换器,因为泛型在运行时是"解析"的,但类型转换在编译时是解析的——框架实际上不为每个
实际上,如果编译器推断类型化变量无法转换为其他类型,则它只捕获DirectCast冲突。
这些是实际等价物:
1 2 3 4 5 | double d = 10; int i = (int)d; Dim d As Double = 10 Dim i As Integer = d |
注意这个结构的危险性,当您在vb.net中只将double赋给integer时,double会意外地被缩减为integer。
而C程序员得到的编译时安全性是不会意外地缩小变量.NET的大小。vb.net程序员必须始终将directcast作为一种安全的编程习惯。
这些是实际等价物:
1 2 3 4 5 6 7 8 9 | // 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) |
[编辑]
@ Dan Tao:
不需要在C_中使用DirectCast,运行时也会阻止从长到整的值的加载。这就是cSuve所主张的,c没有directcast,directcast可以阻止分配不同类型的变量,而"因为"c没有directcast,它会在分配不同类型时默默地出错。但正如你所看到的,情况并非如此,C的演员阵容与DirectCast完全相同。这将导致InvalidcastException运行时错误:
1 2 3 | long l = 10; object o = l; int i = (int)o; |
这也将导致与上述相同的运行时错误:
1 2 3 | Dim l As Long = 10 Dim o As Object = l Dim i As Integer = DirectCast(o, Integer) |
现在,"有趣"的部分就在这里出现了,用vb.net,你必须记住许多关键词才能完成一些事情。在C中,如果一个给定的关键字可以在另一个场景中使用(就像在这个变量的向下转换中一样),他们不会发明另一个关键字来实现它。
在C中,您只需执行以下操作:
1 2 3 | long l = 10; object o = l; int i = (int)(long)o; |
在vb.net中,如果您真的想降低变量的值,并想用正交的方法来实现它,即只记住一个关键字,则必须这样做:
1 2 3 | Dim l As Long = 10 Dim o As Object = l Dim i As Integer = DirectCast(DirectCast(o, Long), Integer) |
但这不会编译,那么如何实现长整型的下推?你必须记住vb.net的其他关键字。而在C中,它是正交的,使用这个构造
1 2 3 | Dim l As Long = 10 Dim o As Object = l Dim i As Integer = CType(o, Integer) |
隐马尔可夫模型。。我认为,cSuve混淆源于c多次使用
这是一个向下的投射…
1 2 | long l = 1; int i = (int) l; |
…不等于:
1 2 | Dim l As Long = 1 Dim i As Integer = DirectCast(l, Integer) |
如果您要执行向下强制转换,则必须执行以下操作:
1 2 | Dim l As Long = 1 Dim i As Integer = CInt(l) ' can also use CType |
现在,如果一个vb.net程序员是故意编程的,而不是在编码时昏昏欲睡,为什么他会在充分意识到DirectCast不能分配不同类型时使用它呢?如果vb.net程序员真正想要的是向下投射,那么他不应该首先尝试DirectCast。现在,vb.net程序员在发现DirectCast不能用于downcast时,必须退格并用cint(或ctype)替换它。
对于引用类型,使用
在c中,从
有趣的是,如果使用一个中间的
我认为这个场景最能说明为什么DirectCast对非对象(object关键字)类型的编译时类型检查安全性有错误的理解,并且只是想退格。好的。
1 2 3 4 5 6 | float f = 10; long l = f; Option Strict On Dim f As Single = 10 Dim l As Long = f |
当发现float不能直接分配给long且无法编译时,C编码人员将执行以下操作:好的。
1 | long l = (long)f; |
这是正确的。好的。
现在,让我们来看看我们的vb.net编码器,一旦发现float不能分配给long,也不能编译,我们将尝试这样做:好的。
1 | Dim l As Long = DirectCast(f, Long) |
几秒钟后…好的。
NET程序员:"请让我做我的出价,请编译,请…!!好的。
在搜索fu和msdn之后的几分钟:好的。
VB.NET程序员:"啊……所以我必须使用这个clng或ctype构造来转换变量。"好的。
1 | Dim l As Long = CLng(f) |
这就是我所说的DirectCast对编译时类型检查安全性的错误理解。如果程序员不知道何时何地应该使用DirectCast,那么DirectCast就是用来退格的。DirectCast是一种不常穿的安全毯。好的。
如果DirectCast最终不被使用,那么它在这个场景中有多有用?好的。
[编辑]好的。
@朱勒好的。
我并不是说所有的vb.net程序员都不知道DirectCast的真正用途,他们中的一些人确实知道DirectCast只用于对象类型(以及装箱在对象中的基元类型)。好的。
一种情况是,一个vb.net编码人员将现有的C代码重新编码到vb.net中,会得出错误的结论,即期望(无论正确与否)的语言彼此对称。好的。
当他在代码中看到这个构造…好的。
1 | TextBox txt = (TextBox)sender; |
…他会把这个翻译成:好的。
1 | Dim txt As TextBox = DirectCast(sender, TextBox) |
这是正确的。好的。
现在,因为我们程序员喜欢对称性,所以我们中的一些人(如果我不知道clng的话,我可能也是)会倾向于转换这段代码…好的。
1 2 3 4 | /* 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 |
……好的。
1 2 | Dim f As Single = file.ReadFloat(0) Dim l As Long = DirectCast(f, Long) |
如果一个C人是将C代码转换为vb.net的人,那么他会因为这里明显缺乏对称性而感到沮丧。好的。
但是对于一个被指派将C代码转换为VB.NET的VB.NET人员来说,他会觉得C编译器不会捕获不兼容的类型分配,而VB.NET会捕获它。现在,对于这个明显的发现,将向他的同事和一些论坛吹嘘vb.net的功能。好的。
但是,恐怕是VB.NET程序员错误地推断了第一个代码的意图。上面C的代码片段开始了它的生命,就像这样最初是这样写的:好的。
1 2 | float f = file.ReadFloat(0); long l = f; |
而这不会编译,C编译器捕获不兼容的类型分配,这与等效的vb.net与
现在,为了将一个变量类型转换成另一个兼容的类型,我们用同样的方式转换这个代码…好的。
1 | TextBox txt = (TextBox)sender; |
…到此代码:好的。
1 | Dim txt As TextBox = DirectCast(sender, Textbox) |
我们必须转换此代码…好的。
1 | long l = (long)f; // will compile |
…到此代码:好的。
1 | Dim l As Long = DirectCast(f, Long) ' will not compile |
但是,遗憾的是,在兼容的原始类型之间进行强制转换时,这并不能编译DirectCast。它没有为上面的C代码提供任何对称性,它不能用于转换兼容的基元类型,尽管它的名称是directcast。好的。
在我看来,DirectCast应该命名为CastObject,因为它无论如何只能在对象类型(以及在对象中装箱的基元类型)之间进行转换。DirectCast实际上不需要分配兼容的基元类型(integer、double及其较低和较高的对应类型)。当在兼容的基元类型之间分配时,DirectCast不再有用,特别是您无论如何都要用退格键替换它,并用适当的替换它。好的。
或者我看到的另一种方式,直接修改CdTcCasic结构,这样它就可以像旧的和新的语言一样兼容类型,例如C,C++,C语言,Java,Delphi,D等。这样做,它将提供VB.NET在其他类型的语言上的对称性。这样做,我们也可以放弃(假设只有这样,我们不能使其他依赖于旧函数的程序失败)所有名称不直接映射到其类型的函数(例如CINT、CDBL、CSNG等),我们只使用DirectCast来代替它们。好的。好啊。
让我们试着给一次在这。 </P >
第一,让我们这是清澈的。这将不会编译: </P >
1 2 3 | //This code uses a type converter to go across an inheritance tree string s ="10"; int i = (int)s; |
VB的CType
在VB中使用,你会: </P >
1 2 | Dim s as String ="10" Dim i as Integer = CType(s, Integer) |
在C #,我会使用: </P >
1 2 | string s ="10"; int i = Convert.ToInt32(s); |
VB的directcast
If it is the correct type, cast it,
otherwise throw an
InvalidCastException.Direct cast can only go up or down a
branch, never across to a different
one.
从解释说,它将是一种直接等价的C #铸造。然而,在C #你会只需要指定的铸造方法铸造式只读操作。铸造上像bluths是可选的。实例: </P >
1 2 3 4 5 6 7 | // 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; |
C #现并不看的任何类型的转换器。它是只读的查找表的任何显式/隐式定义的算子的超负荷的预测型你是试图做出的铸造的。 </P > VB的trycast
你已经understood correctly说,这是相当于一个额外的C # AS关键字。 </P >
你知道你真的很努力来运行你的代码样本吗? </P >
对………………… </P >
1 2 3 | //This code uses a type converter to go across an inheritance tree string s ="10"; int i = (int)s; |
...you posited说,它将运行。它也并不运行 </P >
你有两种类型的演员在# C。没有额外的代码,有好的当量的directcast关键字在C #。。。。。。。"你有没有closest创造它自己是
你有: </P >
1 | My_Object c = (My_Object)object |
和 </P >
1 | My_Object c = object as My_Object |
在第一次的一个,如果fails铸造,它throws是错误的。你是想说,"我知道这个面向的是,如果它是不在了,有一些错误的。" </P >
在第二次,
其他铸造后的诠释: </P >
什么是差分之间的显式和隐式casts??????? </P >
(铸造的)应该是同样的;它throws安invalidcastexception。。。。。。。我尝试这在C #: </P >
1 2 3 | string t ="hello"; object x = t; int j = (int) x; |