实际上,编译器只会在推断出类型变量无法转换为其他类型时才会捕获 DirectCast 违规。
以下是实际等效项:
double d = 10;
int i = (int)d;
Dim d As Double = 10
Dim i As Integer = d
请注意此结构的危险性。当您仅在VB.NET中将double分配给整数时,double将意外地缩小为整数。
而C#程序员在.NET中获得了编译时安全性,不会意外缩小变量。 VB.NET程序员必须始终使用DirectCast作为安全编程习惯。
这些是实际等效项:
double d = 10;
int i = d;
Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)
关于丹·陶的评论:
C#中没有必要使用DirectCast。运行时也会防止将long类型转换为整数类型的值。这就是OP所争论的,即C#没有DirectCast,而DirectCast可以防止分配不同类型的变量,而“由于”C#没有这个DirectCast,它将在分配不同类型时引发静默错误。但正如您所看到的,事实并非如此。C#的强制转换与DirectCast完全相同。这将导致InvalidCastException运行时错误:
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#中,如果一个给定的关键字可以在另一种情况下使用(比如在这个变量向下转换的例子中),他们不会发明另一个关键字来实现它。
在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)
但是这样不会编译,那么我们如何将 long 强制转换为 integer 呢?你必须记住 VB.NET 的其他关键字。而在 C# 中,它是正交的,你可以使用这个结构 (typehere)
来取消装箱变量,你也可以使用相同的结构 (typehere)
进行向下/向上转换。在 VB.NET 中,从对象中加载值并进行向下转换之间存在根本性的断开。因此,在 VB.NET 中,你必须这样做:
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = CType(o, Integer)
嗯.. 我认为 OP 的困惑源于 C# 多次使用
(typehere)
。首先,它用于向下转型;其次,同样的结构(请查看此帖子的第一部分,
object o = l
)也用于从对象中取消封箱的值,这个行为具有 DirectCast 的安全类型转换行为。它们是相同的!
这种向下转型...
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)
现在,如果一个 VB.NET 程序员是有意识地编程,而不是在编码时昏昏欲睡,那么他/她为什么会使用 DirectCast 呢?因为他/她完全知道它不能分配不同的类型。如果这个 VB.NET 程序员真正想要的是向下转换,他/她就不应该首先尝试使用 DirectCast。现在,当这个 VB.NET 程序员发现 DirectCast 不能用于向下转换时,必须回退他/她所写的内容,并将其替换为 CInt(或 CType)。
int i = (int)d;
可以执行已知类型的已知转换,但在任何情况下,如果你实际上在VB.NET中使用DirectCast
(即当对象类型在编译时未知时),使用()
进行转换在C#中并不会执行转换--它只是进行强制类型转换。因此,装箱后的双精度浮点数无法作为整数拆箱。基于这个原因,这两种写法是等效的。 - Dan Tao()
和DirectCast
的区别只适用于 值类型 是正确的,但对于 引用类型 是错误的。[对于引用类型,这两者是等效的;不执行任何转换。] 这使得这个比较毫无意义,因为在我看来,没有理由使用DirectCast
来处理 值类型。我的看法是:对于值类型,()
等同于CType
,而对于引用类型,则等同于DirectCast
。 - ToolmakerSteve