Is using "as" in C# a safe way of casting? - c#

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?

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 :)

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:
You don't know for sure what type myObject is
You want to do something with myObject, but only if it's of type MyType
myObject could be something other than MyType, and it won't mean there's a bug
One 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.

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.

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.
}

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.

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)

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
}

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".

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.

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.

If you use as, there won't be a runtime InvalidCastException, but table may be null, so you need to check for that.

Related

Can a cast from object to class ever fail when both are exactly the same?

If I have the following code
object o = new Building(4, "something");
And I attempt the following
if(o.GetType() == typeof(Building))
Building buildingCast = o as Building;
What could go wrong? I want to make sure that buildingCast can never be null from a problematic cast. Is there any way at all that cast could fail? Even something obscure?
The reason I ask is that I am cleaning up a test project and I am trying to weed out redundant code. There are checks against buildingCast possibly being null...
if(buildingCast == null)
etc
...but we cannot reach the code in the if statement.
Don't refactor for the sake of refactoring. If you have the following lines of code in a row
object o = new Building(4, "something");
Building c = o as Building;
Then by all means change it to
Building o = new Building(4, "something");
but if you have something like
public void SomeMethod(object o)
{
//you absolutely need a sanity check here
Building c = o as Building;
if( c == null )
{
//throw exception perhaps
}
//this can also be rewritten as
Building b = null;
if(o != null && o is Building)
b = (Building)o;
else
//throw exception or log..etc
}
If you attempt the following
if(o.GetType == typeof(Building))
Building buildingCast = o as Building;
then you're creating a lot more redundant and in fact this would make the code a lot less readable, you'd have to do something like
Building buildingCast = null; //to be able to use outside the if
if(o.GetType() == typeof(Building))
buildingCast = o as Building;
//you still end up with a null here if cast fails.
//this is the EXACT procedure of the 'as' operator anyway
//which does
Building buildingCast = o is Building ? (Building)o : (Building)null;
..and of course if you are absolutely positive the types are the same by using a check beforehand then the cast will never fail.
Building buildingCast = o as Building;
Usually, you see this kind of code when casting a class o without knowing whether it is the correct type (and able to cast to Building) or whether o is null.
Then, usually you see a null check afterword.
If you see this just above:
Building b = new Building(4, "something");
object o = new Building(4, "something");
Then, the as is redundant.
However, if o is being passed in from some other part of the system, you can never be sure, hence the check.
If the actual type of o is assignable to Building, then this will work. If the actual type is not compatible, you will get null as result. So if o comes from anywhere else than the line above, you should leave the check there.
If you're 100% sure o is of type Building, then declare it as Building. If that's not possible, then you'll need to leave the checks in your code and cast it to one as early as possible. For example, assuming you instantiate it via reflection, and you know the type, then you should cast it immediately.
BTW, casting via as already performs the type check for you. If the type isn't applicable, it returns null.
I read through the answers and it seems like no one really points out that as is not a cast, have a look at http://msdn.microsoft.com/en-us/library/vstudio/cscsdfbt.aspx for more information.
Quoting the important section:
Note that the as operator performs only reference conversions, nullable conversions, and boxing conversions. The as operator can't perform other conversions, such as user-defined conversions, which should instead be performed by using cast expressions.
Put in a bit descriptive (but not 100% correct) terms it means that as tries to change the type of the pointer and sees if it is possible to see what it is referencing as another type, but it will never try to call a casting operator, implicit or not. A huge difference from a low-level point of view.
And I'd also like to recommand you to have a look at is here http://msdn.microsoft.com/en-us/library/scekt9xw(v=vs.80).aspx which basically is a obj.GetType() == typeof(sometype) on steriods (and you get rid of the issue of obj being null).
In general you use as when "converting" to an interface. as does not allow for coercion, so the object must be an implementation of the correct type.
Those three lines of code should never fail.
However, there might be a case where a function is called with a parameter that isn't expected, due to a bug somewhere else in the program or someone calling a function incorrectly.
So, it's always good to have a check to make sure you got what you expected.

Why ever cast reference types when you can use "as"? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Casting: (NewType) vs. Object as NewType
In C#, why ever cast reference types when you can use "as"?
Casting can generate exceptions whereas "as" will evaulate to null if the casting fails.
Wouldn't "as" be easier to use with reference types in all cases?
eg:
MyObject as DataGridView
rather than,
(DataGridView)MyObject
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.)
operator 'as' work with reference types only.
Sometimes, you want the exception to be thrown. Sometimes, you want to try to convert and nulls are OK. As already stated, as will not work with value types.
One definite reason is that the object is, or could be (when writing a generic method, you may not know at coding-time) being cast to a value type, in which case as isn't allowed.
One more dubious reason is that you already know that the object is of the type in question. Just how dubious depends on how you already know that. In the following case:
if(obj is MyType)
DoMyTypeStuff((MyType)obj);
else
DoMoreGeneralStuff(obj);
It's hard to justify using as here, as the only thing it really does is add a redundant check (maybe it'll be optimised away, maybe it won't). At the other extreme, if you are half-way to a trance state with the amount of information you've got in you're brain's paged-in memory and on the basis of that you are pretty sure that the object must be of the type in question, maybe it's better to add in the check.
Another good reason is that the difference between being of the wrong type and being null gets hidden by as. If it's reasonable to be passing in a string to a given method, including a null string, but it's not reasonable to pass in an int, then val as string has just made the incorrect usage look like a completely different correct usage, and you've just made the bug harder to find and potentially more damaging.
Finally, maybe if you don't know the type of the object, the calling code should. If the calling code has called yours incorrectly, they should receive an exception. To either allow the InvalidCastException to pass back, or to catch it and throw an InvalidArgument exception or similar is a reasonable and clear means of doing so.
If, when you write the code to make the cast, you are sure that the cast should work, you should use (DataGridView)MyObject. This way, if the cast fails in the future, your assumption about the type of MyObject will cause an invalid cast exception at the point where you make the cast, instead of a null reference exception at some point later.
If you do want to handle the case where MyObject is not a DataGridView, then use as, and presumably check for it being null before doing anything with it.
tl;dr If your code assumes something, and that assumption is wrong at run-time, the code should throw an exception.
From MSDN (as (C# reference)):
the as operator only performs reference conversions and boxing conversions. The as operator cannot perform other conversions, such as user-defined conversions, which should instead be performed using cast expressions.
Taking into consideration all of the comments, we came across this just the other day and wondered why you would do a direct cast over using the keyword as. What if you want the cast to fail? This is sometimes the desirable effect you want from a cast if you're casting from a null object. You then push the exception up the call stack.
So, if you want something to fail, use a direct cast, if you're okay with it not failing, use the as keyword.
As is faster and doesn't throw exceptions. Therefore it is generally preferred. Reasons to use casts include:
Using as, you can only assign types that are lower in the inheritance tree to ones that are higher. For example:
object o = "abc" as object;
DataGridView d = "abc" as DataGridView // doesn't do anything
DataGridView could create a custom cast that does allow this. Casts are defined on the target type and therefore allow everything, as long as it's defined.
Another problem with as is that it doesn't 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 can't use as on those because they can never be null. This means you'll have to put a constraint on T, while it is actually unnecesary. If you don't know whether you're going to have a reference type or not, you can never use as.
Of course, you should always check for null when you use the as keyword. Don't assume no exceptions will be thrown just becase the keyword doesn't throw any. Don't put a Try {} Catch(NullReferenceException){} around it, that't unneccesary and bloat. Just assign the value to a variable and check for null before you use it. Never use it inline in a method call.

Should I use (ObjectType) or 'as ObjectType' when casting in c#? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Casting: (NewType) vs. Object as NewType
Say for example I have a class called MyObjectType and I want to convert the sender parameter of an event to this type. I would usually go about it by simply doing this:
MyObjectType senderAsMyType = (MyObjectType) sender;
I've recently realised that it can also be done like this:
MyObjectType senderAsMyType = sender as MyObjectType;
Which way is most efficient? So that I can make my code consistent and use one of the ways throughout. Or do they both have pro's and cons? If so please could someone inform me of them.
Thanks again,
If you wish to avoid any InvalidCastExceptions use
MyObjectType senderAsMyType = sender as MyObjectType;
otherwise use
MyObjectType senderAsMyType = (MyObjectType)sender;
if an InvalidCastException represents a true exceptional situation in your application.
As for performance, I would contend that you would find no discernible difference between the two different kinds of casting. I was interested though so I used Jon Skeet's BenchmarkHelper and achieved results that confirmed my suspicions:
Test:
using System;
using BenchmarkHelper;
class Program
{
static void Main()
{
Object input = "test";
String output = "test";
var results = TestSuite.Create("Casting", input, output)
.Add(cast)
.Add(asCast)
.RunTests()
.ScaleByBest(ScalingMode.VaryDuration);
results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
results.FindBest());
}
static String cast(Object o)
{
return (String)o;
}
static String asCast(Object o)
{
return o as String;
}
}
Output:
============ Casting ============
cast 30.021 1.00
asCast 30.153 1.00
I think this answer will help...
Casting: (NewType) vs. Object as NewType
Basic difference: if sender is not an instance of MyObjectType or one of its subclasses, the first example (direct cast) throws an exception; the second (as operator) returns null.
None of them is plainly better or worse; you should use the one or the other according to the situation you are facing at the moment. If sender is not a MyObjectType what do you want to do? probably, in this case, since it's an event handler, throwing exception is perfectly fine...
You should use (MyObjectType) whenever possible, because you will get an exception right away if the cast fails. With as you might get a NullRef-exception anywhere later.
Use as only when you handle a failed cast right afterwards.
They do slightly different things. It depends on what you want.
// Will throw an exception if the cast cannot be made
MyObjectType foo = (MyObjectType)bar;
or
// Will return null if the cast cannot be made
MyObjectType foo = bar as MyObjectType;
Which you use is up to you? If you expect the cast to potentially fail frequently (and you are happy with that) go for as and test for null afterwards, if you expect it never to fail go for (type).
Remember, that if the reference can be null anyway and you need to know that too, test for null before the cast.
MyObjectType senderAsMyType = (MyObjectType) sender;
This will throw an InvalidCastException if sender cannot be cast to MyObjectType.
MyObjectType senderAsMyType = sender as MyObjectType;
senderAsMyType will be null if sender cannot be cast to MyObject. This method cannot be used with value types.
I believe the latter is marginally faster, but the difference is virtually insignificant.
It depends on your expectations of your objects. If the object should be of that type, and you need to access that objects members, use:
MyObjectType senderAsMyType = (MyObjectType) sender;
As stated before, this throws an InvalidCastException for you if it is invalid
If it might be of that type, and you only want to take action if it is, use 'as', and check for null
MyObjectType senderAsMyType = sender as MyObjectType;
if(senderAsMyType != null)
{
senderAsMyType.MyMethod()
}
However if you are only checking the type, but do not need the object, use the 'is' operator, as this will be cheapest resource-wise
if(sender is MyObjectType)
//do something
Don't worry too much about efficiency, it's better to make the decision based on semantics. Whether one is more efficient than the other will depend heavily on individual circumstance, and how many times you expect it to fail.
A straight cast "(ObjectType)" can fail, and will throw an InvalidCastException.
"as" will not fail with an exception, but instead will return a null object if the cast doesn't work.
If the cast is definitely valid, just do the cast. That way if things go wrong you will get the exception and hopefully be able to solve the problem.
If you aren't certain of the object type, it can be useful to use "as" and just check for null
From the best practises perspective you should use the as keyword if you expect objects of different types and your code can handle them, e.g.
public void MyFunction(MyObject obj)
{
obj.DoSomething();
SpecializedObject specialized = obj as SpecializedObject;
if(specialized!=null)
{
specialized.DoSthSpecial();
}
}
And use the normal cast when you are sure the type will be what you expect, you just need to cast it because of technical reasons:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyObject));
MyObject obj = (MyObject)xmlSerializer.Deserialize(xml);
this way its not only faster, but also doesn't hide errors.

What is the difference between casting and using "as" in C#?

If there is a difference, what is the difference between the two ways of doing the following cast?
In this case e is a GridViewRowEventArgs object.
GridView gv = (GridView)e.Row.FindControl("gv"); //first way
GridView gv2 = e.Row.FindControl("gv") as GridView; //second way
The differences are:
If a cast fails, it throws an InvalidCastException.
If the as operator fails, it just returns a null reference.
You can't use as with non-nullable value types (e.g. you can't do "o as int").
The cast operator is also used for unboxing. (as can be used to unbox to a nullable value type.)
The cast operator can also perform user-defined conversions.
EDIT: I've written elsewhere about when I feel it's appropriate to use which operator. That might be worth a read...
What isn't mentioned in the above answers is intent -- why are you performing the conversion, and (more importantly) what happens on the lines after the conversion?
For example, I've seen code similar to the following a number of times:
if ((foo as SomeType).SomeMethod()) { /* ... */ }
This could be compared to the cast-using version:
if (((SomeType) foo).SomeMethod()) { /* ... */ }
So, which of these is better?
The cast is.
Using as will result in a NullReferenceException if the conversion fails.
Using a cast will result in an InvalidCastException if the conversion fails.
Now tell me, which is a more useful exception for debugging? A NullReferenceException, which could be produced by nearly anything, or an InvalidCastException, which lets you know what actually went wrong?
Thus, only use as if the conversion is actually optional (meaning that there must be a null check before using the variable). Otherwise, use a cast, thus making your intentions more explicit.
The safe cast as
variable as type
does the same as
(variable is type) ? (type)variable : (type)null
and will not work for value types.
In general, the difference between a static cast and "as", is that the cast will throw an Exception if it fails, whereas "as" will just set the variable to null.
The "as" statement basically makes an attempt to cast the variable, and returns null if it fails rather than throwing an exception. As such, the value to which you're casting must be nullable - a reference type or a nullable primitive. In your example, you'd have to do:
int? i2 = o as int;
or it won't compile.
If you however used a reference type say Table the first one would raise InvalidCastException in case o was not assignable to Table and the second would just return null.
Apart from the issue which Jon pointed out, the as keyword effectively casts o as SomeClass. If o isn't derived from SomeClass it returns null. Whereas a simple cast would throw an exception.
SomeClass i2 = o as SomeClass;
becomes
SomeClass i2;
if (o is SomeClass)
i2 = (SomeClass)o;
else
i2 = null;
I might be stating the obvious here, but one thing that you get with the 'as' cast is, that you are guaranteed to end up with an object of the type you requested.
This comes in handy in certain situations.

Are there compelling reasons AGAINST using the C# keyword "as"?

I find that using the following:
TreeViewItem i = sender as TreeViewItem;
if(i != null){ ... }
is easier to write and understand than:
if(sender.GetType() == typeof(TreeViewItem)){
TreeViewItem i = (TreeViewItem)sender;
...
}
Are there compelling reasons not to use the first construct?
I prefer casts to as in most cases because usually if the type of the object is wrong, that indicates a bug. Bugs should cause exceptions IMO - and an InvalidCastException at exactly the line which performs the cast is a lot clearer than a NullReferenceExceptionmuch later in the code.
as should be used when it's valid and legal to have been passed a reference to an object of the type that you don't want. That situation does come up, but not as often as normal casting in my experience.
Comparing types using GetType(), however, is very rarely the right solution - it's only appropriate when you want to check for the exact type involved rather than a compatible type.
I've written a significantly longer answer about the "cast vs as" discussion elsewhere.
Not at all - it gives you the chance to verify that the conversion (cast) was done OK. If you do
TreeViewItem i = (TreeViewItem) sender;
you might get an exception if the cast fails.
Generally speaking, these two snippets are not equivalent. TreeViewItem i = sender as TreeViewItem will yield a correct result even if sender is a grand-grand-child of TreeViewItem, whereas sender.GetType() == typeof(TreeViewItem) will be true only when sender is precisely TreeViewItem and none of its possible subclasses.
"as": good stuff. use it all the time.
if you really want an alternative to manually comparing types try:
if(person is Employee) { }
reads better yet.
Your example would be better written as:
if (sender is TreeViewItem) {
TreeViewItem i = (TreeViewItem)sender;
...
}
It is exactly this dual type checking that the as operator can help avoid. So for your cited example, I would say it is definitely a good solution.
However, there are situations where you really do want a cast. If you're expecting a TreeViewItem and want nothing else, casting will ensure an InvalidCastException is thrown if you're given anything else.
Just like in most situations, there is no blanket rule here: use the right tool for the right job.
If you want a plain (not nullable) value type, obviously this won't work, eg:
int test = sender as int;
isn't valid, however:
int? test = sender as int?;
is allowed.
No, I use it quite a bit. It allows you to avoid InvalidCastExceptions in a clean way.
For example:
TreeViewItem tvItem = sender as TreeViewItem;
if (tvItem != null) return;
// Do stuff
as opposed to:
try
{
TreeViewItem tvItem = (TreeViewItem)sender;
// Do stuff.
}
catch (InvalidCastException ex)
{
// Didn't work, do something about it
return; // ... or not...
}
"as" is faster, but things to bear in mind are:
"as" returns a null instead of throwing an exception if that's a problem
it won't do custom conversions iirc
it doesn't work for reference->value
Edit: "as" definitely is faster (http://www.codeproject.com/KB/cs/csharpcasts.aspx)
Edit2: so basically a speed vs safety decision
If getting the wrong type would be a bug, then you should use a cast. The reason for this is that there really is a problem and you should know about it.
If it is possible that the value will be null, and that is not a bug in the system when this happens then use "as". The reason being that you should use "as" any time that getting a null back is acceptable.
Keep in mind that you can't use "as" to convert to value types, because the null value is not acceptable for them. If you have a value type and want to use "as", you will need to use a nullable value type.
When to Use "as" Versus Casting

Categories

Resources