This is a story of two types: GenericType and SpecificType, where GenericType is 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
1. Generation 5 » Prefix-casting versus as-casting in C#
Subscribe to our RSS Feed | About Us
Prefix-casting versus as-casting in C#
Introduction
This is a story of two types: GenericType and SpecificType, where GenericType is 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 of AnotherSpecificType, 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. Ascasting, 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) {
http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/[1/16/2014 3:55:16 PM]
Search for:
Search
Archives
June 2012 (1)
August 2010 (1)
May 2010 (1)
June 2009 (2)
April 2009 (1)
March 2009 (1)
February 2009 (3)
January 2009 (3)
November 2008 (1)
August 2008 (2)
July 2008 (5)
June 2008 (5)
May 2008 (2)
April 2008 (6)
March 2008 (8)
June 2006 (1)
February 2006 (1)
Categories
AJAX (2)
Asynchronous Communications (16)
Biology (1)
Books (1)
Design (1)
Distributed (1)
Exceptions (2)
Functional Programming (1)
GIS (1)
Ithaca (1)
Japan (1)
Math (1)
Media (3)
Nature (1)
Semantic Web (3)
Tools (28)
CRUD (1)
Dot Net (17)
Freebase (2)
GWT (9)
Java (7)
Linq (2)
PHP (6)
Server Frameworks (1)
Silverlight (12)
SQL (5)
Uncategorized (1)
Web (2)
Analytics (1)
2. Generation 5 » Prefix-casting versus as-casting in C#
[10]
[11]
[12]
[13]
[14] }
List boppable=thing as IBoppable;
if (boppable !=null) {
boppable.Bop()
}
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.)
Paul Houle on June 13th 2008 in Dot Net
Comments (13)
Comments (13)
Login
Sort by: Date Rating Last Activity
Michael james · 291 weeks ago
+2
Great post, i learnt something new today. I always use type cast but have colleagues that use as.
Knowing the difference will be a great help
Reply
Will · 291 weeks ago
0
I disagree. I'd say the rule of thumb is:
If you cannot continue if the cast fails, then use the prefix style cast, which will result in an exception.
If you can continue if the cast fails, then use a combination of "if object is type ... " and "as" casts.
You should NEVER do this:
MyType t;
try { t = (MyType)foo; }
catch { // do something here if cast fails and return }
// do something here if cast succeeds and return
That's a situation where "is" and "as" operators are useful. An example would be checking addins to
see if they implement IDisposable. You won't know this at compile time, so you'll have to make some
type of check.
I've found that the majority of time I can handle invalid casts more often than not, so the majority of
http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/[1/16/2014 3:55:16 PM]
3. Generation 5 » Prefix-casting versus as-casting in C#
time I'm using "is" and "as".
Reply
Janko · 291 weeks ago
0
Very good article!
Reply
cristian · 291 weeks ago
0
Hi there, nice post. I think you should mention or write a post about about explicit type conversion. It's
an important distinction of "prefix-casting".
Reply
Sebastian · 291 weeks ago
0
I don't think articles about performance in .Net 1.1 should be used as a reference in 2008. Just read
the article's comments or try it yourself before making such conclusions.
IF you want performance then do the _exact opposite_ of your "IBobbable" example. The first snippet
(as) will use isinst (and a branch instruction) whereas the is-cast snippet will use isinst and castclass. A
quick test shows a performance gain of about 12%, whew! This as-null pattern is the only place I use
that operator. And now guess which use of "as" can be found in the "as keyword [C#]" SDK article ;) .
Reply
Tim C · 291 weeks ago
0
"as" is faster? Sample code to back that up? In my testing it was for all intents and purposes EXACTLY
the same.
Reply
Zack Owens · 291 weeks ago
+1
I'm not quite sure there is a situation that would require one type of cast over the other when you are
dealing with classes or interfaces. Both are interchangeable syntactically and logically.
But also keep in mind that the as operator will only work for classes and interfaces. You must use the
prefix cast when working with an enum or struct. The is operator, however, will work with enums and
structs.
Reply
Maarten Oosterhoff · 291 weeks ago
0
Another difference is that value types cannot be cast using the 'as' keyword, you must us prefix-casting
for value-types.
I usually use the is/as keyword, I find that works best for me to understand the code.
Nice article though!
Reply
Petar Petrov · 291 weeks ago
0
I totally agree with Will.
I always use "as" operator over "is"+"as". However there is situations where I want to force the type so
I use the prefix cast.
Reply
Anu Viswan · 281 weeks ago
Hi
I would disagree with you on the latter part in which you mentioned "as" casting is faster.
Can you provide some code sample to support your claim ??
http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/[1/16/2014 3:55:16 PM]
0