What’s the difference between "as" and "cast" operators?

Most people will tell you that the difference between “(Alpha) bravo” and “bravo as Alpha” is that the former throws an exception if the conversion fails, whereas the latter returns null. Though this is correct, and this is the most obvious difference, it’s not the only difference. There are pitfalls to watch out for here.

First off, since the result of the “as” operator can be null, the resulting type has to be one that takes a null value: either a reference type or a nullable value type. You cannot do “as int”, that doesn’t make any sense. If the argument isn’t an int, then what should the return value be? The type of the “as” expression is always the named type so it needs to be a type that can take a null.

Second, the cast operator, as I’ve discussed before, is a strange beast. It means two contradictory things: “check to see if this object really is of this type, throw if it is not” and “this object is not of the given type; find me an equivalent value that belongs to the given type”. The latter meaning of the cast operator is not shared by the “as” operator. If you say

short s = (short)123;int? i = s as int?;

then you’re out of luck. The “as” operator will not make the representation-changing conversions from short to nullable int like the cast operator would. Similarly, if you have class Alpha and unrelated class Bravo, with a user-defined conversion from Bravo to Alpha, then “(Alpha) bravo” will run the user-defined conversion, but “bravo as Alpha” will not. The “as” operator only considers reference, boxing and unboxing conversions.

And finally, of course the use cases of the two operators are superficially similar, but semantically quite different. A cast communicates to the reader “I am certain that this conversion is legal and I am willing to take a runtime exception if I’m wrong”. The “as” operator communicates “I don’t know if this conversion is legal or not; we’re going to give it a try and see how it goes”.

I did some testing and it also appears the "as" operator handles one more special case: Converting from a ValueType to Nullable<T>. (Or is this considered a boxing and unboxing conversion) The code below worked for me:

Ok since I’m not a C# programmer: Just curious where would you want to use the “as” operator instead of an explicit cast?

I think I covered that in the article, but to sum up, here are two ways to think about it.

First, “as” means “I expect that sometimes this will not succeed, give me null in those cases”. A cast means “I expect that this will always succeed; if I am wrong, then please crash the program”.

Second, “as” means “I want to know what this object *really is*, not what it is convertible to by some representation-changing specially-defined conversion rule. A cast means “convert this thing using whatever crazy mechanism you need to do to make it work.”

Choose the one that matches the meaning you intend to implement. — Eric

I mean as we all know (thanks to this blog at least 😉 ) things get implemented because many people want/need them and it’s worth the cost of implementation, or is the as operator just a byproduct of something else?

Apparently people write it because they consider "as" to be more "aesthetically pleasing" than cast with its extra parentheses (and I can’t blame that for it, to be honest – C cast syntax is one of the worst parts of the language, second only to pointer/array declarators), and ignore other implications, such as the intended semantics of the cast.

To rewrite this using as instead doesn’t look quite so tidy. Maybe you could put the as operation and assignment inside the IF condition and then check the value returned by the assignment operator, but that doesn’t look so nice.

Besides, I would hope that a good compiler would optimise is-followed-by-as into a single operation anyway. No idea if any do.

The ‘as’ operator seems to be one of the most abused operators at my workplace. When asked, most devs say they use it "because it looks better." What often results, however, is that improper casts aren’t caught until they try to use the null reference later on in the code. Consider this example:

var someObject = (object)new SomeType();

<bunch of code>

var A = someObject as ADifferentType;

var B = (ADifferentType)someObject;

<whole bunch of code>

<whole bunch of code>

<whole bunch of code>

A.DoSomething();

B.DoSomething();

Assume here that ADifferentType does NOT derive from SomeType. In this example, the ‘as’ operator sets A to null because it’s not the proper type. However you don’t catch that until much later in the code (and in the extreme case, in an entirely different method), where you try to reference it. This makes debugging difficult. On the other hand, when we try to direct cast to variable B, we get an exception immediately and our bug is pinpointed on the spot.

In the world of generics (and therefore mostly type safe code), I find the ‘as’ operator is almost never appropriate. I have a standing rule with my devs that if they find themselves tempted to use ‘as’, come down and see me because, except for a few rare circumstances, it almost always indicates an architectural problem.

@Bill…. As of 2010 Beta 1, the compiler (neither C# nor JIT) perofrms that type of operation, and these can be long running operations. Your code effectively is:

if ((o as SomeClass) != null)

{

SomeClass sc = o as SomeClass;

}

Would you EVER code that directly???

@Mike…If you consider the use of RTTI (Runtime Type Identification) based logic to be an "architectural problem", then I agree with your post. However I consider it (RTTI) to be avaluable tool. If you are going to "restrict" the use of "as", then IMPO, to be consistant you must place the EXACT same restraints on "is".

That’s a pity I think. It seems a simple optimisation, but I’ve never written a compiler so I can’t really say. The fact we’re having this conversation at all would indicate its a common enough thing that programmers do.

"Would you EVER code that directly???"

No, I wouldn’t. I’d use the is operator instead. It looks simple enough with one if operation on its own, but I’m thinking more of a long else-if chain, and we only get the if-condition to do our thing.

I think of casts a mild code smell, much like comments. When I have one, I want to take a minute to ask whether there’s another design that wouldn’t need it, and whether that design is attractive in other ways.

In C#, comments are easy to find, thanks to their unique and obvious syntax.

If C# had chosen a syntax like C++’s dynamic_cast<> operator, it would be easy to find them, but it didn’t. C# casts are not syntactically obvious, since parens are used for a lot of things. At least ‘is’ and ‘as’ are easy to find, but casts are not, and it’s too late to change the language to help.

My wish (request?) is that the C# tools of the future make it easy to find casts, so I can give them that extra scrutiny.

Another blog I learned something from. I always assumed that (Cast) versus as were identical save for the difference when a failure occurred (in the same way that you have int.Parse + int.TryParse).

Mike: Well said. I also see a lot of similar things.

It’s especially insidious when people speculatively cast something and then hand the reference off to another method to deal with it. You get a failure down the line and that failure is now potentially a long ways away from the site of the cast, plus it’s a NullRef instead of an InvalidCastException. Even more galling is the fact that tools like ReSharper tell you that this is the case, yet people still ignore the warnings.

I do agree that casting in C# is particularly ugly, though.

((Blah)otherblah).SomeMethod(); is much harder to read and type compared to (otherblah as Blah).SomeMethod();

If anything, the direct cast should’ve been easier to write instead of the speculative cast via "as". Like Mike said, I see it abused quite a lot. I also agree that casting often reeks of a design problem. Sometimes it’s unavoidable, but most of the time it’s indicative of a problem in the design.

So noone else here has written an object.Cast<T>() extension method? "foo.Cast<Bar>().Baz()" is pretty easy to read to me. I also use object.IfType<T>(Action<T>) instead of as, which I find easier to read as well, but then again, I also prefer "enumerable.Each(x => Console.WriteLine(x))", so I’m probably not the best person to ask here…

tobi: A null can be cast with () to any reference type for which the code compiles. With as, it obviously returns null as well. If you are casting with () to a non-nullable value type, you’d get an exception.

I’m curious why “(foo as Bar).Baz()” is considered an anti-pattern. Is it just because of the potential for a null-reference exception?

No. You’re looking at this too narrowly. — Eric

I’ve used this from time to time in combination with the “as” operator, for example:

if (x is Foo) { (x as Foo).M(); }else if (x is Bar) { (x as Bar).N(); }else if (x is Baz) { (x as Baz).P(); }else { throw new NotImplementedException(); }

Obviously it doesn’t happen often, but if the base class doesn’t have a discriminator property then it’s kind of the only way to deal with class hierarchies.

Given that we’ve already validated x to be a Foo, Bar, whatever, then there’s no way to get a null reference inside the conditional. Same goes with a class that’s expected to implement some, but not all, of some set of interfaces – just change (Foo, Bar, Baz) to (IFoo, IBar, IBaz).

…and so on, and I guess this is the most efficient and “correct” way, but even this oversimplified example gives me a headache to look at. It’s not about aesthetics, not really, it’s just that the way it’s structured doesn’t even come close to expressing its real intent. The first version clearly presents itself as “x is going to be exactly one of these things, and depending on which one it is, we have to do something different with it.”

And there’s the broader problem right there. — Eric

Is there a better way that I’m not aware of?

You’re looking at the problem at the wrong level. The problem isn’t that the result might be null. The problem is that the type check is needed in the first place. Let’s make your example slightly less abstract:

What do we conclude about this? I conclude that the author of this method has no clear idea what “Frob” means for any given Animal! The fact that you have an Animal but then need to do something special depending on whether its a Dog, Mammal or Butterfly indicates a design problem in the Frob method’s class; Frob probably should actually be three separate methods. It’s also deeply unfortunate that Frob provides a trap for the unwary caller. Frob’s contract looks like “I can handle any animal”, but clearly it cannot. Again, this is evidence that Frob needs to be several different methods.

Another tack: notice that essentially what I’m doing here is simulating a virtual call on a non-existent Frob method on Animal. We could therefore also conclude that some virtual method is missing from Animal, again indicating a potential design problem, this time with the class hierarchy. But either way, something here is messed up. — Eric

Eric — I have to agree with your response to Aaron that this type of pattern is a potential design problem. But often this situation is unavoidable. Often we do not have the option to go back and add a virtual method to the base class and implement them in the sub classes. Extending your Animal example, what do you do when you need to add a new method "void TagAndRelease()" but are unable to modify class Animal and all it’s sub classes? Each sub class needs to have a different implementation.

With version 3.5 of C# and before, the only option I see is using the "is" and "as" operators with lots of "if" statements like others have discussed. Does anyone know another way?

With version 4.0 of C# the new "dynamic" functionality could be used if you create a specific method for each sub class.

> If anything, the direct cast should’ve been easier to write instead of the speculative cast via "as".

I second (third?) that, though I’m not sure about which syntax I would actually prefer for that. Personally I’ve always liked ML/F# syntax of "(x : T).y", but that would conflict with operator?: so it is not an option. I also like functional cast syntax which Delphi uses (and where, I believe, C# got "as" from): "T(x).y", and, so far as I can see, it would not introduce any quiet changes to existing code, but that has the potential of being confused with instance creation – as many other languages, such as Python and F#, use it for that.

I actually like VB operators for that, their names are really pretty clear. If you do an up/down/interface cast which you assert will succeed, you use DirectCast(). For the same where the cast may not succeed and you need to check, you use TryCast(). For conversions (where representation changes), you use CType(), where "C" stands for "change".

> To rewrite this using as instead doesn’t look quite so tidy. Maybe you could put the as operation and assignment inside the IF condition and then check the value returned by the assignment operator, but that doesn’t look so nice.

> With version 3.5 of C# and before, the only option I see is using the "is" and "as" operators with lots of "if" statements like others have discussed. Does anyone know another way?

From my observations, a "typeswitch" construct for C# is one of the more frequent feature suggestions on Connect. It would be nice to have that, as it’d also remove most of the need for is/as – if you can do a check and bind a result of that check to a scoped identifier all at once, that’s usually all that is actually needed. That said, it’s purely a convenience feature, and would probably be used less than, say, auto properties, so if Eric says that those have barely got in the language, I don’t have high hopes for typeswitch.

> How do the casting operators behave when they encounter a null reference?

The semantics are pretty much common sense. Any cast to a reference type or to a nullable value type will return "null" – which, by the way, means that even if (T)x didn’t throw, it doesn’t mean that (x is T)==true, so you still need that null check. Unboxing to a non-nullable value type will throw.

> I’m curious why "(foo as Bar).Baz()" is considered an anti-pattern. Is it just because of the potential for a null-reference exception?

It’s because you’re essentially saying two contradictory things in a single expression. When you use "as", you say "maybe this isn’t really a Bar, so please don’t throw right there, but tell me instead. When you use operator. on the result, you say "this is never null", which implies "this is always a Bar".

From a pragmatic point of view, if a cast failed, I want to get InvalidCastException, and not NullReferenceException. The latter can happen for numerous reasons, which would complicate the investigation somewhat. The former unambiguously identifiers the real problem.

Of course, it’s a much bigger deal when people don’t use the result of "as" without a null-check immediately, but when they pass it to some method (which passes it to another method, which raises an event which stores it in a property …), and then somewhere down the line (and much later) some code tries to use that value as if it wasn’t null, and dies. That kind of thing can be notoriously hard to debug.

Making sure all non-private methods throw ArgumentNullException whenever null isn’t explicitly a sensible argument helps a lot in the null-propagation scenario as far as finding the problem goes. Of course it’s still a lot better to immediately throw an exception, and infinitely better to immediately throw an exception that actually specifically tells you what’s wrong.

I’ve noticed that my WPF code is full of the dreaded is/as (anti-)pattern. For one thing, there are objects all over the place: ValueConverters, events, DataContexts, and more, all deal just with objects. I frequently need to know "do I have a List? how about a List of strings? a Dictionary? a plain IEnumerable?" or "is this a textbox? a checkbox? a listbox?" and I don’t see a cleaner way to avoid the is/as if-block.

@Gabe, the block itself is not a problem in the scenario which you describe. The problem is a double check. You should use "as" followed by a null check in typeswitch scenarios, not "is" followed by cast or ‘as". If you use StyleCop, it will actually point that one out (and, IIRC, so will ReSharper).

@Aaron, as far as a "better way" it largely depends if you have any control over the class hierarchy. If you can add a "Dispatch" method to each class in the hierarchy, then the "Double Dispatch" design pattern can be applied. This is very effective when two class hierarchies need to interact in a manner specific to the actual instance within each hierarchy (since C# – like many other languages evaluates parameters for a match based on declared and not actual type).

If you do NOT have any control, then a potential alternative [IMHO it is subjective if it os "better" or not] is to build the dispatch using reflection

Liked your note on the usage of the «dynamic» keyword for dynamic method dispatching.

Many times I have missed this type of method dispatching: I first fell in love with the LISP programming language (CLOS, defgeneric, defmethod…).

With the dynamic cast one explicitly states: "I wan’t dynamic method dispatching on this call; please choose the most specific method overload, at run-time, according to the specific type that appears in this variable".

And with methods of more than one parameter, non-dynamic parameters can statically reduce the set of possible method overloads, while dynamically parameters finally choose one at run-time.

Anyway, as tempting as it seems, and being a (somewhat) conscious programmer, I wonder whether the pattern should be used at all. How does it compare in speed to the normal already mentioned patterns? Would it be a sin to use it?

If it is much slower, however, it does seem possible that the compiler could provide an optimization for such use (?).

As long as it "looks" good, I’m almost sure a lot of people will be using it!

Also, with this post, I realized that casts may do conversions, if needed, to achieve their goal (that of returning a value of (i.e. assignable to) the specified type, null, or throw).

@Gabe, if you want neat over fast, you can always write a typeswitch yourself using lambdas and method chaining. It’s trivially done (searching on MSDN blogs should find you some implementations), and it looks much neater, but it’s somewhat slow because of delegate virtual calls overhead.

Mark: Polymorphism is fine, but I didn’t create the class hierarchy. Even if I subclass everything that I might need a value from, I can’t get the rest of the world to use my subclasses; a DataGrid will always use a TextBox and there’s no way to tell it to use my subclass; I have to interoperate with code that is already written, libraries I don’t maintain. I’m sure you get the idea. Extension methods would be nice, but that only works if you know the types at compile-time.

Which one better expresses the intent of the code? Which one is easier to read? Which is easier to understand? I think the first one wins on all counts. In particular, the Select class is something I would have to write, which means it’s 100+ lines of generic metaprogramming code that has to be maintained by my organization. Since the Select<>() idiom is not standard, you really have to study it to figure out what it does.

And the whole reason we don’t like the first option is the slight perf hit of having the redundant "is", so it doesn’t make sense to replace the extra "is" with a method call, a delegate call, and all the other logic inside the Case functions. Not to mention that the first option stops executing the logic when it finds a matching type, while the second option still has to make a function call for each Case regardless of whether it does anything, plus it has the overhead of constructing a new Select instance for every child of the form.

I’m probably a little late to be posting another reply here, but I might as well try to clarify something.

I’ve come across a number of instances where double dispatch would be inappropriate, inadvisable, or just plain impossible. For example:

– Database entities. Unless you can show me an entity framework that does a competent job of handling multi-table hierarchies and supports OO concepts like abstract base classes and double dispatch, the result is often a mess of conditionals to account for the impedance mismatch between domain class hierarchies and discrete entities. I love Linq to SQL, but it’s not up to that particular task, and neither has any other ORM that I’ve tried.

– UI functions. In any medium-to-large scale app you are very likely to have some kind of middle tier that contains "business logic" but is UI independent (some consumers may not even *have* a UI). Without some crazy code-injection technique like AOP or virtual extension methods, it’s somewhere between impractical and impossible to make the class capable of instantiating its own editor. Let’s say you’re representing several types of these (related) objects in a tree or list view and the user has initiated an edit – how do you know what editor to bring up? Again, I think you’re pretty much stuck with the mess of conditionals; you might have access to a discriminator and be able to use a switch statement, but that’s only making the code nicer, not solving the design problem we’ve described.

– UI control hierarchies. It’s a *very* frequent occurrence that some particular Winforms control re-implements some non-virtual property as "new", and if you fall into the trap of always accessing it through the base class then you’re in big trouble. I don’t know about anyone else, but in my experience, the "Text" property is notorious for behaving strangely. This may be poor design, but it’s also someone else’s design, there’s nothing I can do about it.

– Messaging. You’re communicating with some hardware device that may have sent you any of a dozen or maybe a hundred different messages, none of which have anything important in common (except for being "messages"). You have to respond to the message, but first, you obviously have to figure out what it is. Similar to above, if you have control over the message class hierarchy, you can add a discriminator so your handling code can be a nicer switch statement, but it still suffers from the same problems described in the earlier reply (the contract says that it can handle any message, even though maybe it can’t, and the author may indeed have no idea at all what "HandleMessage" means for any given message).

Maybe I just haven’t been out there long enough to know the "right" solutions for these, but in my limited experience, the only truly elegant solution is dynamic programming, and I assume that’s why the C# team is working on it for C# 4. (And in a sense, dynamic typing doesn’t really make the design problem go away, it just provides a more convenient way of expressing the workaround).

I also like the typeswitch that Pavel mentions but, of course, that is just syntactic sugar, it’s not any more efficient or safe than the is/as ladder and doesn’t make the underlying design any better.

@Aaron G (and any other interested reader). If you have been folowing the information available for 4.0, the primary (but not sole) reason given for dynamic is for interop with other languages, and NOT for functionallity directly contained in C# or other strongly typed languages.

In my professional opinion, considering AOP, code injection or IL rewriting as "some crazy technique" is at best short sighted. Consider that something as fundamental as code contracts is impleented in exactly this fashon.

I have successfully used "synthesized double dispatch" (ie multiple calls occur, but NO conditional branching) in all 4 of the categories you mention. This is NOT to say that such an approach is always a good choice, but it is one that can be considered.

I can be contacted as david "dot" corbin "at" dynconcepts "dot" com by anyone interested in these approaches.

I'm new to C# and have been reading your blogs. They are very nice and informative. Thanks for them.

I may be wrong but please clear my doubt.

I have a question here:

You have written in this blog:

["….The "as" operator will not make the representation-changing conversions from short to nullable int like the cast operator would….The "as" operator only considers reference, boxing and unboxing conversions."]

This means that boxing and unboxing are not representation-changing conversions and so "as" handles them.