tags:

views:

1559

answers:

11

Consider the following code:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

What is the difference between the three types of casting(okay, 3rd one is not a casting, but you get the intent... ), and which one should be preferred?

A: 

'as' is based on 'is', which is a keyword that checks at runtime if the object is polimorphycally compatible (basically if a cast can be made) and returns null if the check fails.

These two are equivalent:

Using 'as':

string s = o as string;

Using 'is':

if(o is string) 
    s = o;
else
    s = null;

On the contrary, the c-style cast is made also at runtime, but throws an exception if the cast cannot be made.

Just to add an important fact:

The 'as' keyword only works with reference types. You cannot do:

// I swear i is an int
int number = i as int;

In those cases you have to use casting.

Sergio Acosta
'is' works on any type
leppie
Thanks for pointing my mistake, you are right. I edited the answer. oops, sorry.
Sergio Acosta
+28  A: 
  1. Throws InvalidCastException if o is not a string. Otherwise, assigns o to s, even if o is null.
  2. Assigns null to s if o is not a string or if o is null. For this reason, you cannot use it with value types (the operator could never return null in that case). Otherwise, assigns o to s
  3. Causes a NullReferenceException of o is null. Assigns whatever o.ToString() returns to s, no matter what type o is.

Use 1 for most conversions - it's simple and straightforward. I tend to almost never use 2 since if something is not the right type, I usually expect an exception to occur. I have only seen a need for this return-null type of functionality with badly designed libraries which use error codes (e.g. return null = error, instead of using exceptions).

3 is not a cast and is just a method invocation. Use it for when you need the string representation of a non-string object.

Sander
You can assign 'null' to value-types when explicitly defined, e.g.:int? i;string s = "5";i = s as int; // i is now 5s = null;i = s as int; // i is now null
Anheledir
RE: AnheledirActually i would be null after the first call. You have to use an explicit conversion function to get the value of a string.
Guvante
RE: Sander Actually there is another very good reason to use as, it simplifies your checking code (Check for null rather then check for null and correct type) This is helpful since a lot of the time you would rather throw a custom one exception. But it is very true that blind as calls are bad.
Guvante
#2 is handy for things like Equals methods where you don't know the input type.Generally though, yes, 1 would be preferred. Although preferred over that would obviously be using the type system to restrict to one type when you only expect one :)
Calum
#2 is also useful when you have code that might do something specific for a specialised type but otherwise would do nothing.
AnthonyWJones
+5  A: 

It really depends on whether you know if o is a string and what you want to do with it. If your comment means that o really really is a string, I'd prefer the straight (string)o cast - it's unlikely to fail.

The biggest advantage of using the straight cast is that when it fails, you get an InvalidCastException, which tells you pretty much what went wrong.

With the as operator, if o isn't a string, s is set to null, which is handy if you're unsure and want to test s:

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

However, if you don't perform that test, you'll use s later and have a NullReferenceException thrown. These tend to be more common and a lot harder to track down once they happens out in the wild, as nearly every line dereferences a variable and may throw one. On the other hand, if you're trying to cast to a value type (any primitive, or structs such as DateTime), you have to use the straight cast - the as won't work.

In the special case of converting to a string, every object has a ToString, so your third method may be okay if o isn't null and you think the ToString method might do what you want.

Blair Conrad
A: 

"(string)o" will result in an InvalidCastException as there's no direct cast.

"o as string" will result in s being a null reference, rather than an exception being thron.

"o.ToString()" isn't a cast of any sort per-se, it's a method that's implemented by object, and thus in one way or another, by every class in .net that "does something" with the instance of the class it's called on and returns a string.

Don't forget that for converting to string, there's also Convert.ToString(someType instanceOfThatType) where someType is one of a set of types, essentially the frameworks base types.

Rob
+3  A: 

Not quite a duplicate, but there are also some performance discussions in a previous question.

Unsliced
Good eye. I searched, but did not find this. :-(
Blair Conrad
+3  A: 
  1. Use when something should definately be the other thing.
  2. Use when something is maybe the other thing.
  3. Use when you don't care what it is but you just want to use the available string representation.
Quibblesome
A: 

2 is useful for casting to a derived type.

Suppose a is an Animal:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

will get a fed with a minimum of casts.

Joel in Gö
+2  A: 

If you already know what type it can cast to, use a C-style cast:

var o = (string) iKnowThisIsAString;

Note that only with a C-style cast can you perform explicit type coercion.

If you don't know whether it's the desired type and you're going to use it if it is, use as keyword:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

Note that as will not call any type conversion operators. It will only be non-null if the object is not null and natively of the specified type.

Use ToString() to get a human-readable string representation of any object, even if it can't cast to string.

Mark Cidade
That's an interesting little gotcha regarding the type conversion operators. I have a few types that I've created conversions for, must watch out for that then.
AnthonyWJones
A: 
string s = o as string; // 2

Is prefered, as it avoids the performance penalty of double casting. Here's my take on it (at the bottom, 'The As keyword instead of explicit casting')

Chris S
A: 

The as keyword is good in asp.net when you use the FindControl method.

Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
     ...
}

This means you can operate on the typed variable rather then having to then cast it from object like you would with a direct cast:

object linkObj = this.FindControl("linkid");
if (link != null)
{
     Hyperlink link = (Hyperlink)linkObj;
}

It's not a huge thing, but it saves lines of code and variable assignment, plus it's more readable

Glenn Slaven
A: 

According to experiments run on this page: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(this page is having some "illegal referrer" errors show up sometimes, so just refresh if it does)

Conclusion is, the "as" operator is normally faster than a cast. Sometimes by many times faster, sometimes just barely faster.

I peronsonally thing "as" is also more readable.

So, since it is both faster and "safer" (wont throw exception), and possibly easier to read, I recommend using "as" all the time.

boomhauer