Prefix-casting versus as-casting in C#

本文探讨了C#中两种类型的显式转换:前缀转换(prefix cast)与as转换(as cast)。这两种转换方式在失败时的行为不同,前者会在转换失败时抛出异常,而后者则返回null。文章详细分析了这两种转换方式的优缺点,并给出了具体的使用场景建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来自:http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/

Introduction

This is a story of two types: GenericType and SpecificType, where GenericTypeis a superclass of SpecificType. There are two types of explicit cast in C#:

The Prefix cast:

[01] GenericType g=...;
[02] SpecificType t=(SpecificType) g;

The as cast:

[03] GenericType g=...;
[04] SpecificType t=g as SpecificType;

Most programmers have a habit of using one or the other — this isn’t usually a conscious decision, but more of a function of which form a programmer saw first. I, for instance, programmed in Java before I learned C#, so I was already in the prefix cast habit. People with a Visual Basic background often do the opposite. There are real differences between the two casting operators which can make a difference in the reliability and performance of your application.

Prefix casting: Reliable Casting

The major difference between prefix- and as-casting is what happens when the cast fails. Imagine, for instance, that g is really an instance ofAnotherSpecificType, which is not a subclass of SpecificType. In this case, the prefix-cast throws an exception at line [2] — however, the as-cast returns null when the cast fails, letting the execution of the program barrel on.

It’s easier to implement correct error handling in programs that use prefix-casting, and programs that use prefix-casting are easier to debug. Prefix-casting causes an exception to be thrown at the moment of the cast, where the problem is obvious. As-casting, on the other hand, can cause an exception to be thrown at the moment where the SpecificType t is referenced. The used of the SpecificType can be far away in the program: it can be in another method, or another class — it could even happen hours after the cast is performed. Be it in development or production, bugs caused by corrupted data structures can be maddeningly difficult to find and correct.

As-casting: Fast Casting

If it’s harder to write correct programs with as-casting, why would anybody use it? For one thing, as-casting is faster than prefix casting by quite a lot. Benchmarks show that as-casting is about five times faster than prefix casting. That said, the performance of casting is only going to matter in the innermost of loops of most programs. The fastest kind of casting is no casting at all: it’s best to use generics to eliminate the need for casting when possible and to move casting outside loops. (Generics also improve the reliability of your code because they help C#’s static type checking catch mistakes.)

There are some cases where as-casting could be convenient, for instance, when you expect the cast to fail sometimes. Often I like to ‘tag’ classes with interfaces that specify certain behaviors. For example,

[05] public Interface IBoppable {
[06]     void Bop();
[07] }

Now i might want to loop through a bunch of Thing objects, and bop all the ones that implement IBoppable: it’s reasonable to use as-casting here:

[08] List<Thing> list=...
[09] foreach(Thing thing in list) {
[10]    List boppable=thing as IBoppable;
[11]    if (boppable !=null) {
[12]        boppable.Bop()
[13]    }
[14] }

It’s OK to use as-casting if you’re going to check to see if the value is null immediately after the cast. The above code is correct, but has the bad smell that the boppable variable continues to exist in the block after the cast… It’s still there for a later maintainer to use erroneously. In cases like this, code can be made clearer with the is operator:

[15] List<Thing> list=...
[16] foreach(Thing thing in list) {
[17]    if(thing is IBoppable) {
[18]        ((IBoppable) boppable).Bop()
[19]    }
[20] }

(Speed freaks can use as-cast on line 18, as we know it’s not going to fail.)

The pattern of testing for null after an as-cast has a few problems. (i) It doesn’t distinguish between the case of the original object being null from the case of the original object being the wrong type and (ii) correct error handling often requires more contorted logic than using an exception — and once you added test logic, you’ve lost the speed advantage of as-casting.

Conclusion

C# offers two casting operators: the prefix-cast and the as-cast. Although the two operators compile to different op-codes in the CLR, the practical difference between them is in how they handle failed casts. Prefix-cast throws an exception on cast failure, while as-cast returns null. It’s easier to implement correct error handling when you use prefix cast, because it doesn’t require manual checks for null values that can cause problems in distant parts of your program. Prefix-cast should be the default cast operator on your fingertips, that you use for everyday situations — reserve as-cast for special cases where performance matters. (For best performance, however, eliminate the cast entirely.)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值