我认为这种情况最好地总结了为什么 DirectCast 对非对象(对象关键字)类型的编译时类型检查安全性有一种错误的感觉,并且只是为了退格。
float f = 10;
long l = f;
Option Strict On
Dim f As Single = 10
Dim l As Long = f
AC# 编码器在发现 float 不能直接分配给 long 并且不会编译时,将执行以下操作:
long l = (long)f;
哪个是对的。
现在,让我们转向我们的 VB.NET 编码器,在发现 float 不能分配给 long 并且不会编译时,将尝试这样做:
Dim l As Long = DirectCast(f, Long)
几秒钟后……
VB.NET 程序员:“请让我听命,请编译,请……!!!”
经过一些谷歌搜索和 MSDN 浏览片刻之后:
VB.NET 程序员:“啊……所以我必须使用这个 CLng 或 CType 构造来转换变量”
Dim l As Long = CLng(f)
这就是我所说的 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 的人,他会因为这里明显缺乏对称性而感到沮丧。
但是对于负责将 C# 代码转换为 VB.NET 的 VB.NET 人员,他会得到这样的印象,即 C# 编译器不会捕获不兼容的类型分配,而 VB.NET 会捕获它。现在,对于这个明显的发现,他将向他的同事和一些论坛吹嘘 VB.NET 的特性。
但以免 VB.NET 程序员错误地推断出第一个代码的意图。上面的 C# 代码片段是这样开始的,最初是这样写的:
float f = file.ReadFloat(0);
long l = f;
而且这不会编译,C# 编译器会捕获不兼容的类型分配,就像等效的 VB.NETOption Strict On
也不会编译它一样(尽管只有在Option Strict
设置为时才不会编译On
,太宽松了)。所以我们需要将 float 类型转换为 long 使用(long)
. 变成这样:long l = (long)f;
现在将一种变量类型转换为另一种兼容类型,与我们转换此代码的方式相同...
TextBox txt = (TextBox)sender;
...到此代码:
Dim txt As TextBox = DirectCast(sender, Textbox)
我们必须转换这段代码......
long l = (long)f; // Will compile
...到此代码:
Dim l As Long = DirectCast(f, Long) ' Will not compile
但是,唉,这不会编译。在兼容的原始类型之间进行转换时,这就是 DirectCast 的不足之处。它与上面的 C# 代码没有任何对称性,并且它不能用于转换兼容的原始类型,尽管它的名称是 Direct Cast。
在我看来,DirectCast 应该被命名为CastObject,因为无论如何它只能在对象类型(以及装在对象中的原始类型)之间进行转换。DirectCast 确实与分配兼容的原始类型(整数、双精度以及它们的较低和较高对应物)无关。在兼容的原始类型之间进行分配时,DirectCast 不再有用,尤其是您无论如何都会退格它,并用适当的类型替换它。
或者我看到的另一种方式,应该修改 DirectCast 构造,因此它可以像新旧语言那样转换兼容类型,例如,C、C++、C#、Java、Delphi、D 等。这样做,在类型转换方面,它将为 VB.NET 提供与其他语言的显着对称性。这样做,我们也可以丢弃(仅假设,我们不能使依赖旧函数的其他程序失败)所有名称不直接映射到其类型的函数(例如,CInt、CDbl、CSng 等)。 . 我们将只使用 DirectCast 来代替它们。