Prefix casting versus as-casting in c#

999 views

Published on

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

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

Prefix casting versus as-casting in c#

  1. 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. 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. 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
  4. 4. Generation 5 » Prefix-casting versus as-casting in C# Thanks Anu Reply Paul Houle · 281 weeks ago +2 @Anu, according to reports I've seen, the performance of as- and prefix casts have largely converged as of .net 3.5. It would be interesting to run tests on mono as well. At this point, I think people should use whatever convention they think is better from a sofware engineering standpoint. In most cases, I think it's better to get an exception early rather than face a null pointer deference later. On the other hand, there are definitely cases where the as-cast semantics are exactly what you want. Reply Anu Viswan · 281 weeks ago 0 Thanks Paul for your kind reply. I understand the speed difference is trivial and doesnt really makes too much impact in real life application. Only thing that would matter is how each handle exception, which again you were spot on that its better to catch an exception earlier than face null later. I was just curious about the differnce. After i read your article, i tried out my little study on differnce and it seems like prefix casting uses "castclass" function in the IL code generated while "as" casting would use isinst. Reading about these IL commands, made me wunder again. Did you happen to check out the differnce in IL ? Reply BlahaK · 79 weeks ago 0 Hi, could anybody help me? I am trying to use prefix-casting dynamicaly by this way: ' long userID = (Type.GetType("long"))mySqlDataReader.GetValue(i); ' Of course it does not work, maybe because "long" is "struct"? .NET says "Cannot implicitly convert 'System.Type' to 'long'. So my question is: how to do this? Thanks for your help. Reply Post a new comment Enter text right here! Comment as a Guest, or login: Name Email Website (optional) Displayed next to your comments. Not displayed publicly. If you have a website, link to it here. None Subscribe to None Submit Comment Copyright © 2013 Generation 5. WordPress Theme design. http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/[1/16/2014 3:55:16 PM]

×