I've been reading up on SharePoint 2010 for work and I've noticed that many code examples I run into from books to instructional videos are cast SharePoint objects in a way I never knew existed in C# (and thought was VB exclusive):
SPWeb web = properties.Feature.Parent as SPWeb;
I'm so used to casting (outside of VB) this way (SPWeb)properties.Feature.Parent and was just curious if there was any particular reason most pieces on SharePoint I've encountered use the VB-esque casting notation.
as is called the safe cast operator in C#. There is a semantic difference between that and a normal cast. A safe cast will not throw an exception if the type cannot be cast; it will return null. A normal cast throws InvalidCastException if the type cannot be cast.
In other words, this code assigns null if Parent if not of type SPWeb:
SPWeb web = properties.Feature.Parent as SPWeb;
While the other version throws if Parent is not of the correct type:
SPWeb web = (SPWeb)properties.Feature.Parent;
The as operator can be quite useful if you don't know for sure that an object can be cast to the desired type - in this case it is common to use as and then check for null. as only works on reference types, since value types cannot be null.
This is also explained in this longer article on MSDN.
By the way, the equivalent operator in VB is TryCast (versus DirectCast).
obj as T
is syntax sugar for
obj is T ? (T)obj : null
Thus, it is a "safe" cast. However, it takes longer, in theory. Thus, you should use normal casting unless you specifically want null if an object is not of the expected type. More often, you are better off handling it manually:
if (!(obj is T))
{
// Handle the case where obj is of an unexpected type.
}
T tobj = (T)obj;
Using the as keyword will set the variable web to null if the Parent is not of type SPWeb.
As where an explicit cast will throw an exception if the Parent is not of type SPWeb.
"as" is safer than (cast) as it will either return a value as the given type or null.
You will find that the following line will (or should) test for null.
If the cast fails the variable assigned to becomes null opposed to throwing an exception 'InvalidCastException '
Related
I have one question..
Which has more effective performance? Or which take less time to execute and Why?
session["var"].ToString()
or
(string)session["var"]
ToString() is a method and (string) is casting (Explicit). IMO casting is always fast
A cast operation between reference types does not change the run-time
type of the underlying object; it only changes the type of the value
that is being used as a reference to that object.
Source: Explicit Conversions
.ToString() can be called from any object. This method is inherited from object class and can be overloaded
.(string) is a cast, Its not a function call. It should be used when it is sure that the object is already in string, it will throw an exception when it can't convert to string including null
Depends on the type of object this session var is, if you know it is a string, option 2 is best.
The latter performs better, simply casting the value to a different type. The former involves a method call and/or a new object creation.
These 2 calls are performing very different actions (unless you knwow for sure that the value is string). So asking which one is faster is not completely correct.
There are arguments both ways which one will be faster since both operations require call to a function. The right approach is to prototype and measure.
Note that it is unlikley that accessing data from Session will be your main performance botleneck (especially in case of SQL or other out-of-process session state).
ToString() raise exception when the object is null. So in the case of object.ToString(), if object is null, it raise NullReferenceException. Convert.ToString() return string.Empty in case of null object. (string) cast assign the object in case of null. So in case of
MyObject o = (string)NullObject;
But when you use o to access any property, it will raise NullReferenceException.
Convert.ToString internally uses value.ToString. Casting to a String is cheaper since that doesn't require an external function call, just internal type checking. It is at least twice as fast to cast Object to String than to call Object.toString()
Is there a way to check whether a C# cast will be successful? In some cases; based on how a rendered page is put together; inheriting from different Master Pages, some casts will work and others will not.
I am wondering how I can check to see if a cast will be successful or if I just have to catch and handle an invalid cast exception.
You can say :
if (Variable is Typename) {
}
Or
Variable = OtherVariable as TypeName;
Variable will be null if casting was not possible.
alternatively, you can use "as" keyword to cast and check if the result is null.
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.
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.
I've recently started working with JSON and the ExtJs framework and I've come across the following code in an example.
we retrieve the information from the frontend using this:
object updatedConfig = JavaScriptConvert.DeserializeObject(Request["dataForm"]);
Then in the example they do the following:
JavaScriptObject jsObj = updatedConfig as JavaScriptObject;
I've never seen the "as" keyword used like that before. Is this just another form of explicitly boxing the updatedConfig variable as a JavaScriptObject or is there something I'm not understanding about this?
Thanks
This is known as a safe cast. What is does is it attempts to cast from one type to another and if the cast fails it returns null instead of throwing an InvalidCastException.
There are actually two separate IL instructions to handle the difference between "as" casting and normal static casting. The following C# code contains both types of casting:
using System;
class Program
{
static void Main()
{
Object o = null;
String s0 = (String)o;
String s1 = o as String;
}
}
The first cast uses the castclass IL instruction and the second cast uses the isinst instruction.
Please see Casting vs using the 'as' keyword in the CLR for a more detailed explanation.
The as keyword is a safer way to cast objects in C#.
SomeType a = obj as SomeType;
Means that if obj is of type SomeType, obj will be cast into that type. If obj is null or is not of type SomeType, a will be null.
Another advantage of the as keyword is that it will throw a compile time exception if the type can not be cast where as (cast) doesn't break until run-time.
Also, it's important to remember that "as" operates in the reference not in the object itself. That's why it can return null instead of throwing an exception, because the object will remain intact. And that's why you can only do it on reference types.
Normally it does not matter that much, but if you implement a casting function (like here in MSDN) it will not be invoked by using as operator.
So, the as operator is useful to "move up and down the inheritance hiearchy": If you have a class Person, you can do:
Person p = new Person();
ojbect o = p as object;
p = o as Person;
But in all cases the object in memory won't be modified in any way, just the reference to it.
Hope that helps