92

What is actually the difference between these two casts?

SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;

Normally, shouldn't they both be explicit casts to the specified type?

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • 1
    See also http://stackoverflow.com/questions/496096/casting-vs-using-the-as-keyword-in-the-clr. This one was first, but that one has a good answer. – Jay Bazuzi Mar 30 '10 at 21:35
  • 1
    You have posted the second oldest question that is a duplicate of another (the first one is locked)! Congratulations, I guess? – gparyani Oct 09 '13 at 02:17
  • Which is funny because this one was posted 3 months earlier :) But the other one has more detailed answers. – Michael Stum Oct 09 '13 at 02:25

12 Answers12

88

The former will throw an exception if the source type can't be cast to the target type. The latter will result in sc2 being a null reference, but no exception.

[Edit]

My original answer is certainly the most pronounced difference, but as Eric Lippert points out, it's not the only one. Other differences include:

  • You can't use the 'as' operator to cast to a type that doesn't accept 'null' as a value
  • You can't use 'as' to convert things, like numbers to a different representation (float to int, for example).

And finally, using 'as' vs. the cast operator, you're also saying "I'm not sure if this will succeed."

Rytmis
  • 31,467
  • 8
  • 60
  • 69
27

Also note that you can only use the as keyword with a reference type or a nullable type

ie:

double d = 5.34;
int i = d as int;

will not compile

double d = 5.34;
int i = (int)d;

will compile.

denny
  • 1,481
  • 1
  • 17
  • 26
11

Typecasting using "as" is of course much faster when the cast fails, as it avoids the expense of throwing an exception.

But it is not faster when the cast succeeds. The graph at http://www.codeproject.com/KB/cs/csharpcasts.aspx is misleading because it doesn't explain what it's measuring.

The bottom line is:

  • If you expect the cast to succeed (i.e. a failure would be exceptional), use a cast.

  • If you don't know if it will succeed, use the "as" operator and test the result for null.

Joe
  • 122,218
  • 32
  • 205
  • 338
6

Well the 'as' operator "helps" you bury your problem way lower because when it is provided an incompatible instance it will return null, maybe you'll pass that to a method which will pass it to another and so on and finally you'll get a NullReferenceException which will make your debugging harder.

Don't abuse it. The direct cast operator is better in 99% of the cases.

Andrei Rînea
  • 20,288
  • 17
  • 117
  • 166
  • 1
    Very sound advice here. Readers, please consider this. – mbadawi23 Sep 01 '17 at 22:06
  • please, this is intentional. This is for you to test your object against multiple types. Or, you have a condition when type is not expected type and you want to do something else. You don't blindly pass it,. You check if it is null and either divert logic or throw exception. This is what it is for. You can't abuse the good thing. – T.S. Mar 24 '22 at 20:19
5

A difference between the two approaches is that the the first ((SomeClass)obj) may cause a type converter to be called.

Cristian Libardo
  • 9,260
  • 3
  • 35
  • 41
4

Here is a good way to remember the process that each of them follow that I use when trying to decide which is better for my circumstance.

DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);

and the next should be easy to guess what it does

DateTime i = value as DateTime;

in the first case if the value cannot be cast than an exception is thrown in the second case if the value cannot be cast, i is set to null.

So in the first case a hard stop is made if the cast fails in the second cast a soft stop is made and you might encounter a NullReferenceException later on.

Nick Berardi
  • 54,393
  • 15
  • 113
  • 135
3

To expand on Rytmis's comment, you can't use the as keyword for structs (Value Types), as they have no null value.

Community
  • 1
  • 1
Omer van Kloeten
  • 11,800
  • 9
  • 42
  • 53
3

All of this applies to reference types, value types cannot use the as keyword as they cannot be null.

//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;


//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;

The cast syntax is quicker, but only when successful, it's much slower to fail.

Best practice is to use as when you don't know the type:

//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;

//use as to find the right type
if( ( sc = someObject as SomeClass ) != null ) 
{
    //do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null ) 
{
    //do something with soc
}

However if you are absolutely sure that someObject is an instance of SomeClass then use cast.

In .Net 2 or above generics mean that you very rarely need to have an un-typed instance of a reference class, so the latter is less often used.

Keith
  • 150,284
  • 78
  • 298
  • 434
2

For those of you with VB.NET experience, (type) is the same as DirectCast and "as type" is the same as TryCast.

Adam Ruth
  • 3,575
  • 1
  • 21
  • 20
1

The parenthetical cast throws an exception if the cast attempt fails. The "as" cast returns null if the cast attempt fails.

1

They'll throw different exceptions.

() : NullReferenceException
as : InvalidCastException

Which could help for debugging.

The "as" keyword attempts to cast the object and if the cast fails, null is returned. The () cast operator will throw an exception immediately if the cast fails.

Only use the C# "as" keyword where you are expecting the cast to fail in a non-exceptional case. If you are counting on a cast to succeed and unprepared to receive any object that would fail, you should use the () cast operator so that an appropriate and helpful exception is thrown.

For code examples and a further explanation: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

Tanjim Ahmed Khan
  • 650
  • 1
  • 9
  • 21
Steve Willard
  • 16,647
  • 4
  • 28
  • 26
1

It's like the difference between Parse and TryParse. You use TryParse when you expect it might fail, but when you have strong assurance it won't fail you use Parse.

ICR
  • 13,896
  • 4
  • 50
  • 78