在开发博客、在线代码示例和(最近)甚至是一本书中,我经常遇到这样的代码:

var y = x as T;
y.SomeMethod();

或者,更糟糕的是:

(x as T).SomeMethod();

这对我来说没有意义。如果你确定x是类型T,你应该使用直接强制转换:(T)x。如果不确定,可以使用as,但在执行某些操作之前需要检查是否为空。上面的代码所做的就是将一个(有用的)InvalidCastException转换为一个(没用的)NullReferenceException。

难道只有我一个人认为这是对as关键字的公然滥用吗?还是我错过了一些明显的东西,而上面的模式实际上是有意义的?


当前回答

这是我最讨厌的事之一。

Stroustrup的D&E和/或一些我现在找不到的博客文章讨论了to操作符的概念,它将解决https://stackoverflow.com/users/73070/johannes-rossel提出的观点(即,与as相同的语法,但使用DirectCast语义)。

这个没有被实现的原因是因为施法应该会造成疼痛和丑陋,所以你会被推远使用它。

遗憾的是,“聪明的”程序员(通常是书籍作者(Juval Lowy IIRC))以这种方式滥用as来绕过这一点(c++没有提供as,可能是出于这个原因)。

甚至VB也有统一的语法,迫使你选择TryCast或DirectCast,并做出决定!

其他回答

人们如此喜欢as,因为它让他们觉得没有例外……就像盒子上的担保。一个男人在盒子上放了一个华丽的保证,因为他想让你觉得里面温暖舒适。你觉得晚上把那个小盒子放在枕头下面,担保仙女可能会下来留下25美分,对吗,泰德?

回到正题…使用直接强制转换时,可能会出现无效的强制转换异常。因此,人们将as作为一个全面的解决方案应用于他们所有的强制转换需求,因为as(本身)永远不会抛出异常。但有趣的是,在你给出的例子中(x作为T).SomeMethod();您正在用无效的强制转换异常换取空引用异常。当您看到异常时,会混淆真正的问题。

我一般不会用太多。我更喜欢is测试,因为对我来说,它看起来更可读,比尝试强制转换和检查null更有意义。

我认为as关键字可以看作是样式更优雅的版本 dynamic_cast来自c++。

直接强制转换比as关键字更需要一对括号。所以即使在你100%确定是什么类型的情况下,它也减少了视觉上的混乱。

不过我同意例外的情况。但至少对我来说,大多数as的使用都是在之后检查null,我发现这比捕获异常更好。

使用“as”的一个原因是:

T t = obj as T;
 //some other thread changes obj to another type...
if (t != null) action(t); //still works

而不是(坏代码):

if (obj is T)
{
     //bang, some other thread changes obj to another type...
     action((T)obj); //InvalidCastException
}

我经常看到这篇误导性文章的引用,作为“as”比cast更快的证据。

本文中比较明显的误导之一是图表,它没有指出要度量的是什么:我怀疑它度量的是失败的强制转换(其中“as”显然要快得多,因为没有抛出异常)。

如果您花时间进行测量,那么您将看到,当强制转换成功时,强制转换比“as”更快。

我怀疑这可能是“货物崇拜”使用as关键字而不是演员的原因之一。