4

I was wondering what is the better method for Casting objects for C#:

MyClassName test = (MyClassName)object;

MyClassName test = object as MyClassName;

I know already that if you do the first way, you get an exception, and the second way it sets test as null. However, I was wondering why do one over the other? I see the first way a lot, but I like the second way because then I can check for null...

If there isn't a 'better way' of doing it, what are the guidelines for using one way or the other?

Matthew Doyle
  • 1,065
  • 7
  • 22

6 Answers6

8

Not any official guideline, but here's how I'd do it.

If you actually want the exception (i.e. you think that the object can never, ever, be of a different type than MyClassName), use the explicit cast. Example (WinForms):

private void checkbox_CheckedChanged(object sender, EventArgs e) {
    // We've hooked up this event only to CheckBox controls, so:
    CheckBox checkbox = (CheckBox)sender;
    // ...
}

If you want to handle types that are not MyClassName gracefully, use the as keyword.

Thomas
  • 174,939
  • 50
  • 355
  • 478
1

Note that as only works for reference types. If you need to unbox a valuetype, then you must the C-style cast.

James Curran
  • 101,701
  • 37
  • 181
  • 258
0

Well, there is a simple reason to use the as keyword (over casting using brackets): This is because the as operator doesn't throw an exception when it fails but instead fills the variable with null. The check if the value was null checked if the code worked or not.

Note that in the real world you will want exception handling around the whole block, incase the user selects the wrong type of dll, or access to it is denied, or... well, you get the picture. This means you can freely use brackets to cast it - but this is in my opinion a more elegant method of doing something where you want to know if it succeeded or failed.

source: http://www.nullify.net/Article/181.aspx

XpiritO
  • 2,809
  • 5
  • 28
  • 34
0

Using the as keyword is safer as you say, and is the thing to use if you're not 100% sure of the type of the object you're trying to cast. Conversely, use the (cast) method if you want an exception if the cast fails. However, if you're also using is, then as becomes redundant. For example, the following code is quite common:

MyClass mc;

if (someObject is MyClass)
{
   mc = (MyClass)someObject;
}
Graham Clark
  • 12,886
  • 8
  • 50
  • 82
  • 1
    I'd use as in that situation as it results in only one type check as opposed to two. – Matti Virkkunen Apr 01 '10 at 16:53
  • Note the the code actually generated for `if(someObject is MyClass)` is actually `if( (someObject as MyClass) != null)` – James Curran Apr 01 '10 at 16:55
  • Don't use **both** `is` and the `(cast)` syntax, you're incurring the cost of the type check twice. If you've already ascertained the type using `is`, it's perfectly safe to do the cast using `as`, and a lot faster since it can bypass any implicit conversion checks. – Daniel Pryden Apr 01 '10 at 17:03
  • @James Curran: Where did you get this information from? The C# specification does not mention this. In fact, it only mentions how the `as` operator is expanded: "The operation `E as T` produces the same result as `E is T ? (T)(E) : (T)null`, except that `E` is only evaluated once." Given this, it doesn't seem to make sense that the compiler would expand uses of `is` to code that uses `as`! – Graham Clark Apr 01 '10 at 20:24
  • @Graham: I learned that by look at the disassembly of some code in Reflector. – James Curran Apr 01 '10 at 20:30
  • @James: I downloaded the latest version of Reflector, and I'm not getting this. The C# specification also disagrees. I honestly thought the sample in my answer was pretty uncontroversial, and even though MSDN uses almost the same thing, apparently this is all wrong! I'll have to investigate further... – Graham Clark Apr 01 '10 at 21:00
  • @Graham: My point is, if `obj is MyType` returns true, then it is guaranteed that `obj as MyType` will succeed. Therefore, using the `(cast)` syntax is unnecessary, since it only adds a runtime check for implicit type conversions that you aren't going to use anyway. – Daniel Pryden Apr 01 '10 at 21:28
  • @Daniel: Fair enough, I didn't know this, but MSDN has this example! (http://msdn.microsoft.com/en-us/library/scekt9xw(d=lightweight,v=VS.90).aspx) They're not helping here. But Jon Skeet has said this is bad, so who am I to argue? – Graham Clark Apr 01 '10 at 21:28
  • @Graham and @James: After doing a bit of looking, it appears the `is` and `as` operators both use the `isinst` MSIL instruction under the hood. According to MSDN, `isinst` "tests if an object reference is an instance of class, returning either a null reference or an instance of that class or interface." (Source: http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.isinst.aspx ). So it appears that doing `obj as MyType` followed by a check for `null` is actually more efficient than using `is` and then `as`, and definitely more efficient than the `(cast)` syntax. – Daniel Pryden Apr 01 '10 at 21:35
0

If you know that the object is MyClassName, then use the first method (direct cast). If you are unsure, then use the second method and check for null or check the type using is before direct casting:

if (obj is MyClassName)
{
    MyClassName test = (MyClassName)obj;
}
Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
  • Don't use **both** `is` and the `(cast)` syntax, you're incurring the cost of the type check twice. If you've already ascertained the type using `is`, it's perfectly safe to do the cast using `as`, and a lot faster since it can bypass any implicit conversion checks. – Daniel Pryden Apr 01 '10 at 17:03
  • 1
    You're right: http://stackoverflow.com/questions/496096/casting-vs-using-the-as-keyword-in-the-clr. The only problem I have with `as` is that it's a run time error if the cast fails and you forgot to check for null. Testing with `is` before casting prevents that. And I doubt there's any real world performance difference unless you're doing millions of casts in a loop. – Jamie Ide Apr 01 '10 at 17:45
0

Check out this article on Prefix-casting vs As-Casting

The author called prefix casting "Reliable Casting," and as casting "Fast Casting."

He has several good examples of when to use each, and the reasons why fast isn't always better. Hope this helps!

Audie
  • 1,470
  • 10
  • 12
  • 1
    It might be worth pointing out that the benchmark tests this article refers to were done in 2004 on version 1 of the .NET framework and C# 2.0. Looking at the comments suggests that the differences have become much more blurred in newer versions of the framework and the C# compiler. Even going by the original benchmarks, the differences between the two methods are very small for 1 million casts! This seems to be a clear case of write what's clearest, don't bother with pointless micro-optimisations. – Graham Clark Apr 01 '10 at 21:20
  • Good point Graham. I came across an article since this post that said the explicit cast is compiled now to effectively be an as cast with a null check. Thanks for your feedback. I guess the only difference is whether you get a null value or a null exception... – Audie Apr 02 '10 at 17:20