Reputation: 7400
I am wondering if using the keyword "as" in the following code is a safe way (i.e. won't blow up) of casting in C#:
public void abc(ref Object dataSource)
{
DataTable table = dataSource as DataTable;
}
Is there a safer way of casting?
Upvotes: 33
Views: 27197
Reputation: 27803
It is a safe way to cast in the fact that it won't cause an exception. However, it can cause hidden bugs if you are not careful.
When using as
, if the cast fails then the resulting variable is null
. If you don't check for this then you will later get a NullReferenceException
when you attempt to access the variable, and it will be less clear on why it's failing (e.g. is it null
because the cast failed or did something else later cause it to be null)
Upvotes: 3
Reputation: 30715
It depends what you mean by "safe". Ask yourself which is safer: an appliance with a circuit breaker, or one built without it? The one without a fuse is more likely to finish washing your clothes, but it's also more likely to burn your house down.
As you probably know, there are two main ways to do explicit casting in C#:
foo = (MyType)myObject; //Cast myObject to MyType or throw an error
foo = myObject as MyType; //Cast myObject to MyType or set foo to null
The difference is that if the runtime doesn't know how to cast myObject
as MyType
, the first line will throw an exception, while the second will only set foo
to null
. This would happen if the object living in myObject
isn't a MyType
, or if there's no explicit cast to MyType
from whatever myObject
is.
So which one is safer? Well, if "safe" means "won't throw an exception if the cast is invalid," then the as
form is safer. If the casting fails, (MyType)myObject
will blow up immediately, but myObject as MyType
will only blow up if you try to do something to foo
that you can't do to null
(such as calling foo.ToString()
).
On the other hand, sometimes throwing an exception is the safest thing to do. If you have a bug in your code, you probably want to know right away. If myObject
is always expected to be a MyType
, then a failed cast means there's a bug somewhere. If you carry on as though the casting worked, then all of a sudden your program is working with garbage data! It might blow up further down the line, making debugging difficult, or - worse - it might never blow up at all, just quietly do things you didn't expect. That could cause all kinds of havoc.
So neither form is inherently safe or correct, they're just useful for different things. You would use the myObject as MyType
form if:
myObject
ismyObject
, but only if it's of type MyType
myObject
could be something other than MyType
, and it won't mean there's a bugOne example is when you have a collection of different WebForm controls, and you want to clear all the TextBoxes among them:
foreach (var control in controls)
{
var textbox = control as TextBox;
if (textbox != null)
{
//Now we know it's a TextBox, so we know it has a Text property
textbox.Text = string.Empty;
}
}
This way, your TextBoxes get cleared out, and everything else gets left alone.
Upvotes: 20
Reputation: 340188
The difference between using as
and a normal cast is that if the cast can't be performed (because the object isn't the right type), the as
operator will return null
. A normal cast will throw an exception.
So they're both "safe" - they just have different behaviors when the cast can't be successful.
Upvotes: 1
Reputation: 141598
It won't throw an exception, if that is what you mean by "safe". However, if the cast fails, table
will be null.
DataTable table = dataSource as DataTable;
Does not throw an exception if the cast fails. Will be null instead.
DataTable table = (DataTable)dataSource;
Will throw an exception if the cast fails.
It's safe in that regard, however if it is possible for the cast to fail, then add a null check to handle it.
Upvotes: 4
Reputation: 21713
Depends what you're trying to do:
DataTable table = dataSource as DataTable;
if (table != null) ...
means "dataSource
might be a DataTable
and I'm going to check it's not null
."
DataTable table = (DataTable) dataSource;
means "dataSource
should definitely be a DataTable
and something's badly wrong if it's not".
Upvotes: 2
Reputation: 46034
as
won't blow up, but if the cast fails, the variable will be set to null. You need to check for that case.
DataTable table = dataSource as DataTable;
if (table == null)
{
// handle case here.
}
Upvotes: 4
Reputation: 29664
If you use as, there won't be a runtime InvalidCastException, but table may be null, so you need to check for that.
Upvotes: 0
Reputation: 3207
It's safe in the sense that it will get the job done if dataSource can be casted as a DataTable. But if you are worried about it not casting successfully, you can first check if dataSource.GetType() is equal to the Type you are trying to cast it to.
Upvotes: 0
Reputation: 1500055
It won't blow up... but that doesn't necessarily mean it's safe.
Typically when I use a cast for a reference conversion, it's because I really, really think that the execution-time type is the one I'm specifying. If it's not, that indicates a bug in my code - and I'd rather that manifested itself as an exception.
If you've got bad data in your system, then continuing as if everything was fine is the dangerous path, not the safe path. That's the way that as
will take you, whereas a cast would throw an InvalidCastException
, aborting whatever you're doing before you get the chance to cause mayhem with the bad data.
as
is good if it's valid for the object not to be of the given type - if it doesn't indicate a bug. You almost always see the pattern of:
Foo x = y as Foo;
if (x != null)
{
...
}
See MSDN for more details about what as
does.
Note also that you probably don't want to use ref
in your method. See my article on parameter passing for more details. Most of the time if I see people using ref
a lot, it's because they don't understand what it really means :)
Upvotes: 51
Reputation: 160852
DataTable table = dataSource as DataTable;
Using as
will return null
if the cast is unsuccessful, so no it won't blow up. - that means you will have to handle the case that table
is null
in the rest of your code though.
Upvotes: 5
Reputation: 37164
The 'as' operator won't throw an exception if the cast is invalid. It just returns null. The () approach will throw an exception. So to answer your question, it is the safest way.
Here is essentially the way you need to go about it:
if( x is MyType )
{
MyType y = (MyType) x;
}
or
MyType y = x as MyType;
if( y != null )
{
// Do stuff
}
Upvotes: 2