Consider the following alternatives:
Foo(someObj as SomeClass);
and:
Foo((SomeClass)someObj);
Due to someObj being of the wrong type, the first version passes null
to Foo
. Some time later, this results in a NullReferenceException
being thrown. How much later? Depends on what Foo
does. It might store the null
in a field, and then minutes later it's accessed by some code that expects it to be non-null
.
But with the second version, you find the problem immediately.
Why make it harder to fix bugs?
Update
The OP asked in a comment: isn't is easier to use as
and then check for null
in an if
statement?
If the null
is unexpected and is evidence of a bug in the caller, you could say:
SomeClass c = someObj as SomeClass;
if (c == null)
{
// hmm...
}
What do you do in that if
-block? There are two general solutions. One is to throw an exception, so it is the caller's responsibility to deal with their mistake. In which case it is definitely simpler to write:
SomeClass c = (SomeClass)someObj;
It simply saves you writing the if
/throw
logic by hand.
There is another alternative though. If you have a "stock" implementation of SomeClass
that you are happy to use where nothing better is available (maybe it has methods that do nothing, or return "empty" values, etc.) then you could do this:
SomeClass c = (someObj as SomeClass) ?? _stockImpl;
This will ensure that c
is never null
. But is that really better? What if the caller has a bug; don't you want to help find bugs? By swapping in a default object, you disguise the bug. That sounds like an attractive idea until you waste a week of your life trying to track down a bug.
(In a way this mimics the behaviour of Objective-C, in which any attempt to use a null
reference will never throw; it just silently does nothing.)