一尘不染

即使没有空检查,使用“ as”代替强制转换是否有意义?[关闭]

c#

在开发博客,在线代码示例,以及(最近)甚至是一本书中,我一直对类似的代码code之以鼻:

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

或更糟糕的是:

(x as T).SomeMethod();

这对我来说没有意义。如果您确定x类型为T,则应使用直接强制转换:(T)x。如果不确定,可以使用as但需要检查null后再执行某些操作。上面的代码所做的就是将(有用的)InvalidCastException变成(没用的)NullReferenceException

我是唯一认为这是公然滥用as关键字的人吗?还是我错过了明显的事情,而上述模式确实有意义?


阅读 268

收藏
2020-05-19

共1个答案

一尘不染

您的理解是真的。这听起来像是尝试对我进行微优化。确定类型时,应使用常规演员表。除了生成更明智的异常之外,它还会快速失败。如果你错了你对类型的假设,你的程序将立即失败,你就可以看到失败立即,而不是等待的原因一个NullReferenceException或者ArgumentNullException甚至是一个逻辑上的错误在未来的某个时候。通常,as没有在null某处进行检查的表达式就是代码味道。

另一方面,如果不确定转换是否正确,并期望转换失败,则应使用as包裹有try- catch块的普通转换来代替。此外,as建议在类型检查后再进行强制类型转换后再使用。代替:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

其产生的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()
2020-05-19