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

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

或者,更糟糕的是:

(x as T).SomeMethod();

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

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


当前回答

只是因为人们喜欢它的样子,所以它很有可读性。

让我们面对现实吧:类c语言中的强制转换操作符在可读性方面相当糟糕。我希望它更好,如果c#采用Javascript语法:

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

或者定义一个to操作符,相当于as的强制转换:

object o = 1;
int i = o to int;

其他回答

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

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

99%的情况下,当我使用“as”时,我不确定实际的对象类型是什么

var x = obj as T;
if(x != null){
 //x was type T!
}

我不想捕捉显式的强制转换异常,也不想使用"is"进行两次强制转换:

//I don't like this
if(obj is T){
  var x = (T)obj; 
}

我在这里写了一点:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

我明白你的意思。我同意它的重点:强制转换操作符传达的是“我确信这个对象可以转换为那种类型,如果我错了,我愿意冒一个异常的风险”,而“as”操作符传达的是“我不确定这个对象可以转换为那种类型;如果我错了,就给我一个null。”

然而,有一个微妙的区别。whatever()表示“我知道x不仅可以转换为T,而且这样做只涉及引用或开箱转换,而且x不是空的”。这确实传达了不同于(T)x). whatever()的信息,也许这就是代码作者的意图。

恕我直言,当与空检查结合在一起时是有意义的:

var y = x as T;
if (y != null)
    y.SomeMethod();

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

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

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