Why ever cast reference types when you can use the how?

Possible duplicate:
Casting: (NewType) against an object like NewType

In C #, why have reference types ever been used when you can use the “how”?

Casting can throw exceptions, while "as" will evaulate to null if casting fails.

Wouldn't it be easier to use “with” with reference types in all cases?

eg:

 MyObject as DataGridView 

but not

 (DataGridView)MyObject 
+6
casting c #
source share
8 answers

Consider the following alternatives:

 Foo(someObj as SomeClass); 

and

 Foo((SomeClass)someObj); 

Due to the fact that someObj is of the wrong type, the first version goes from null to Foo . After some time, this NullReferenceException . How much later? Depends on what Foo does. It can store null in the field, and then after a few minutes it gets access to some code that expects it to be non null .

But with the second version, you will immediately find the problem.

Why is it harder to fix errors?

Update

The OP asked in a comment: isn’t it easier to use as , and then check for null in the if ?

If null is unexpected and indicates an error in the caller, you can say:

 SomeClass c = someObj as SomeClass; if (c == null) { // hmm... } 

What are you doing in this if block? There are two general solutions. One of them is to throw an exception, so the responsibility of the caller must be related to their error. In this case, it is definitely easier to write:

 SomeClass c = (SomeClass)someObj; 

It just saves you the trouble of writing if / throw logic.

There is another alternative. If you have an implementation of the "stock" SomeClass , which you are happy to use where nothing is better (perhaps it has methods that do nothing or return "empty" values, etc.), you can do this:

 SomeClass c = (someObj as SomeClass) ?? _stockImpl; 

This ensures that c never null . But is it really better? What if the caller has an error; don't you want to help find errors? Changing the default object will mask the error. It sounds like an attractive idea until you spend a week in your life trying to track down a mistake.

(In a way, this mimics the behavior of Objective-C, in which any attempt to use the null link will never throw, it just does nothing.)

+9
source share

operator 'as' only works with reference types.

+2
source share

Sometimes you want an exception to be thrown. Sometimes you try to convert, and zeros are fine. As already mentioned, as will not work with type values.

+2
source share

If, when you write the code to make the cast, you are sure that the cast should work, you should use (DataGridView)MyObject . That way, if the collection fails in the future, your assumption about the MyObject type will throw an invalid throw exception at the moment you throw instead of a null-reference exception at some point later.

If you want to handle the case when MyObject is not a DataGridView, use as and presumably check that it is null before doing anything with it.

tl; dr If your code assumes something, and this assumption is incorrect at runtime, the code should throw an exception.

+1
source share

One definite reason is that the object is or may be (when writing a general method that you cannot know when coding) a time different from the type of value, in which case as not allowed.

Another dubious reason is that you already know that an object is of type. How doubtful it depends on how you already know this. In the following case:

 if(obj is MyType) DoMyTypeStuff((MyType)obj); else DoMoreGeneralStuff(obj); 

It's hard to justify using as here, since the only thing he really does is add redundant validation (maybe it will be optimized, maybe it won’t). On the other hand, if you are halfway to a trance state with the amount of information that you have, you are crammed with memory in your brain, and based on this, you are sure that the object should be of type, maybe it’s better to add it to the check.

Another good reason is that the difference between the wrong type and zero is hidden as . If it’s prudent to pass a string to this method, including an empty string, but it isn’t prudent to pass to int, then val as string just made the wrong use look like a completely different right use, it just made the error harder to find and potentially more dangerous.

Finally, perhaps if you do not know the type of object, the call code should. If the calling code called you incorrectly, they should get an exception. To either throw an InvalidCastException to return, or catch it and throw an InvalidArgument exception or the like, this is a reasonable and clear way to do this.

+1
source share

From MSDN ( like (link to C #) ):

the as operator performs only link conversions and box transforms. The as operator cannot perform other transformations, such as user-defined transformations, which should instead be performed using expressions.

0
source share

Taking into account all the comments, we came across this only the other day and wondered why you would make a direct throw using the as keyword. What if you want the roll to fail? This is sometimes the desired effect that you want to get from a throw if you throw from a null object. Then you throw an exception from the call stack.

So, if you want something to fail, use direct casting, if you can't handle it, use the as keyword.

0
source share

As faster and does not throw exceptions. Therefore, this is usually preferred. Reasons for using castings include:

Using as, you can assign types that are lower in the inheritance tree, higher. For example:

 object o = "abc" as object; DataGridView d = "abc" as DataGridView // doesn't do anything 

DataGridView can create a custom listing that allows you to do this. Castes are defined on the target type and therefore allow everything while it is defined.

Another problem is that it does not always work. Consider this method:

 IEnumerable<T> GetList<T>(T item) { (from ... select) as IEnumerable<T> } 

This code fails because T could also be a value type. You cannot use them because they can never be empty. This means that you will need to set a limit on T, while this is actually unnecessary. If you do not know whether you will have a reference type or not, you can never use it like that.

Of course, you should always check for null when using the keyword. Do not assume that exceptions will be thrown just because the keyword does not throw. Do not put Try {} Catch(NullReferenceException){} around it, this is not important and is bloated. Just assign a value to a variable and mark zero before using it. Never use it inline in a method call.

0
source share

All Articles