Possible Duplicate:
Direct casting vs 'as' operator?
Where could this operator be useful? Instead of writing this:
Asset a = new Asset();
Stock s = a as Stock; // s is null; no exception thrown
if (s != null) Console.WriteLine (s.SharesOwned);
You'd better write something that throws. I saw tons of
(s != null)
in production code and it really becomes ugly. Exceptions are more descriptive and natural in that way. Even conceptually: how can you get no asset if it is not a stock? It should an exception if it is not a stock.
You often have the case where you don’t want an exception to be thrown because, well, the situation isn’t exceptional. You have a frob
object which you know can be a Foo
, but could also be a Bar
. So you want to perform some action only if it’s a Foo
.
You try to avoid these situations in designs, and use virtual methods instead. But sometimes there’s just no good way around that.
So rather than taking the roundabout way,
if (frob is Foo) {
((Foo) frob).Frobnicate();
}
you do it directly:
var asFoo = frob as Foo;
if (asFoo != null) {
asFoo.Frobnicate();
}
If nothing else, this is at least more efficient since you only need to test for type equality once (inside the as
cast) instead of twice (in the is
and in the cast).
As a concrete example, this is very useful when you want to clear all the input boxes in a form. You could use the following code:
foreach (Control c in this.Controls) {
var tb = c As TextBox;
if (tb != null)
tb.Clear();
}
Using an exception here would make no sense.
You'd better write something that throws
Not necessarily. Users don't like seeing things throwing. You should write code that works. And if it doesn't you'd better handle it appropriately by apologizing to the user. The as
operator can be useful in situations where for example you would attempt a cast and if this cast doesn't work assign a default value to the variable so that the code continues to work with this default value. It would really depend on the context.
as
does an is
and if the is
returns false
assigns null
.
sounds like a song but it's the answer and I use it a lot, like in the FindControl methods of ASP.NET:
Button myButton = e.item.FindControl("myControlId") as Button;
this kind of assignment does not crash or throw simply assigns null if FindControl finds something different than a Button. I like this so much....
If Asset
is inherited from Stock
, then this should be fine. That's the only sort of case where I've seen that work, although you could prolly also use it in the case of interfaces.
Yes, the as
operator is useful, and yes, it can be misused.
If you are sure that some variable x
is of type T
, you should use a regular cast.
T y = (T)x;
If both T1
and T2
are valid types for variable x
, you cau use as
to check the type and perform the cast in one operation.
What are your requirements?
If the asset is a stock print the number of shares owned.
The as
operator is very useful in that case but you will have to check stock != null
. That is implied by the requirement.
Print the number of shares owned of a stock. It is an error if another asset is supplied.
Then you should write code that throws an exception.
Exceptions are not designed for flow control, they are, by definition, exceptions to the normal train of events. If it's acceptable for the conversion to fail, use as
. If, rather, not being able to cast "a" as a Stock should never happen, you can use simple s=(Stock)a;
which will throw it's own exception. You have no control of the exception at this point, though.
The following lets the developer handle the exceptional case much cleaner:
Asset a= new Asset();
Stock s= a as Stock();
if(s == null) {
// Safely exit from call if possible, maybe make calls to logging mechanism or
// other ways of determining why an exception occurred. Also, could throw custom
// Exception if needed with much more detailed info.
} else {
// Continue normal flow
}
You could do:
Asset a= new Asset();
try
{
Stock s= (Stock);
// Continue normal flow
}
catch (InvalidCastException exc)
{
// Safely exit from call if possible, maybe make calls to logging mechanism or
// other ways of determining why an exception occurred. Also, could throw custom
// Exception if needed with much more detailed info.
}
However, that is using the exception as flow control and is costly and bad design.
It depends on your Error Handling policy. I work on code base where we always use casting than using as
operator. However, there are some cases where AS operator is very much useful and faster than exception.
For example, In following case what do you What do you prefer?
public bool Process(int choice)
{
try
{
Thing thing = GetRequiredThing(choice);
SubThing subThing = (SubThing)thing;
}
catch (InvalidCastException ex)
{
// report ex.
return false;
}
}
or
public bool Process(int choice)
{
Thing thing = GetRequiredThing(choice);
SubThing subThing = thing as SubThing;
if (subThing == null)
{
//report error;
return false;
}
}
If is not necessary that you should always use as
operator. Take your call.
精彩评论