在开发博客、在线代码示例和(最近)甚至是一本书中,我经常遇到这样的代码:
var y = x as T;
y.SomeMethod();
或者,更糟糕的是:
(x as T).SomeMethod();
这对我来说没有意义。如果你确定x是类型T,你应该使用直接强制转换:(T)x。如果不确定,可以使用as,但在执行某些操作之前需要检查是否为空。上面的代码所做的就是将一个(有用的)InvalidCastException转换为一个(没用的)NullReferenceException。
难道只有我一个人认为这是对as关键字的公然滥用吗?还是我错过了一些明显的东西,而上面的模式实际上是有意义的?
Your understanding is true. That sounds like trying to micro-optimize to me. You should use a normal cast when you are sure of the type. Besides generating a more sensible exception, it also fails fast. If you're wrong about your assumption about the type, your program will fail immediately and you'll be able to see the cause of failure immediately rather than waiting for a NullReferenceException or ArgumentNullException or even a logical error sometime in the future. In general, an as expression that's not followed by a null check somewhere is a code smell.
另一方面,如果您对强制转换不确定,并期望它失败,则应该使用as,而不是用try-catch块包装的普通强制转换。此外,建议在类型检查和强制转换之后使用as。而不是:
if (x is SomeType)
((SomeType)x).SomeMethod();
它为is关键字生成isinst指令,为强制转换生成castclass指令(有效地执行两次强制转换),你应该使用:
var v = x as SomeType;
if (v != null)
v.SomeMethod();
这只会生成一条isinst指令。前一种方法在多线程应用程序中有一个潜在的缺陷,因为竞态条件可能会导致变量在is检查成功后改变其类型,并在转换行处失败。后一种方法不容易出现这种错误。
不建议在生产代码中使用以下解决方案。如果你真的讨厌c#中的这种基本构造,你可以考虑切换到VB或其他语言。
如果一个人非常讨厌强制转换语法,他/她可以写一个扩展方法来模仿强制转换:
public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
return (T)o;
}
使用整齐的[?语法:
obj.To<SomeType>().SomeMethod()