在开发博客,在线代码示例,以及(最近)甚至是一本书中,我一直对类似的代码code之以鼻:
var y = x as T; y.SomeMethod();
或更糟糕的是:
(x as T).SomeMethod();
这对我来说没有意义。如果您确定x类型为T,则应使用直接强制转换:(T)x。如果不确定,可以使用as但需要检查null后再执行某些操作。上面的代码所做的就是将(有用的)InvalidCastException变成(没用的)NullReferenceException。
x
T
(T)x
as
null
InvalidCastException
NullReferenceException
我是唯一认为这是公然滥用as关键字的人吗?还是我错过了明显的事情,而上述模式确实有意义?
您的理解是真的。这听起来像是尝试对我进行微优化。确定类型时,应使用常规演员表。除了生成更明智的异常之外,它还会快速失败。如果你错了你对类型的假设,你的程序将立即失败,你就可以看到失败立即,而不是等待的原因一个NullReferenceException或者ArgumentNullException甚至是一个逻辑上的错误在未来的某个时候。通常,as没有在null某处进行检查的表达式就是代码味道。
ArgumentNullException
另一方面,如果不确定转换是否正确,并期望转换失败,则应使用as包裹有try- catch块的普通转换来代替。此外,as建议在类型检查后再进行强制类型转换后再使用。代替:
try- catch
if (x is SomeType) ((SomeType)x).SomeMethod();
其产生的isinst指令为is关键字,和castclass指令的投(有效执行转换两次),你应该使用:
isinst
is
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()