Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does it make sense to use "as" instead of a cast even if there is no null check? [closed]

In development blogs, online code examples and (recently) even a book, I keep stumbling about code like this:

var y = x as T;
y.SomeMethod();

or, even worse:

(x as T).SomeMethod();

That doesn't make sense to me. If you are sure that x is of type T, you should use a direct cast: (T)x. If you are not sure, you can use as but need to check for null before performing some operation. All that the above code does is to turn a (useful) InvalidCastException into a (useless) NullReferenceException.

Am I the only one who thinks that this a blatant abuse of the as keyword? Or did I miss something obvious and the above pattern actually makes sense?

like image 484
Heinzi Avatar asked Jan 26 '10 13:01

Heinzi


4 Answers

Your understanding is true. That sounds like trying to micro-optimize to me. You should use a normal cast when you are sure of the type. Besides generating a more sensible exception, it also fails fast. If you're wrong about your assumption about the type, your program will fail immediately and you'll be able to see the cause of failure immediately rather than waiting for a NullReferenceException or ArgumentNullException or even a logical error sometime in the future. In general, an as expression that's not followed by a null check somewhere is a code smell.

On the other hand, if you are not sure about the cast and expect it to fail, you should use as instead of a normal cast wrapped with a try-catch block. Moreover, use of as is recommended over a type check followed by a cast. Instead of:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

which generates an isinst instruction for the is keyword, and a castclass instruction for the cast (effectively performing the cast twice), you should use:

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

This only generates an isinst instruction. The former method has a potential flaw in multithreaded applications as a race condition might cause the variable to change its type after the is check succeeded and fail at the cast line. The latter method is not prone to this error.


The following solution is not recommended for use in production code. If you really hate such a fundamental construct in C#, you might consider switching to VB or some other language.

In case one desperately hates the cast syntax, he/she can write an extension method to mimic the cast:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

and use a neat[?] syntax:

obj.To<SomeType>().SomeMethod()
like image 152
mmx Avatar answered Oct 26 '22 01:10

mmx


IMHO, as just make sense when combined with a null check:

var y = x as T;
if (y != null)
    y.SomeMethod();
like image 40
Rubens Farias Avatar answered Oct 26 '22 01:10

Rubens Farias


Using 'as' does not apply user defined conversions while the cast will use them where appropriate. That can be an important difference in some cases.

like image 40
Larry Fix Avatar answered Oct 26 '22 02:10

Larry Fix


I wrote a bit about this here:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

I understand your point. And I agree with the thrust of it: that a cast operator communicates "I am sure that this object can be converted to that type, and I am willing to risk an exception if I'm wrong", whereas an "as" operator communicates "I am not sure that this object can be converted to that type; give me a null if I'm wrong".

However, there is a subtle difference. (x as T).Whatever() communicates "I know not just that x can be converted to a T, but moreover, that doing so involves only reference or unboxing conversions, and furthermore, that x is not null". That does communicate different information than ((T)x).Whatever(), and perhaps that is what the author of the code intends.

like image 36
Eric Lippert Avatar answered Oct 26 '22 02:10

Eric Lippert