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
Related
Have the following code which works fine.
MyType convertedItem = (MyType)item;
However I get a compiler error from
var convertedItem = item as MyType;
Cannot convert type 'OtherType' to 'MyType' via a reference
conversion, boxing conversion, unboxing conversion, wrapping
conversion, or null type conversion.
Can anyone explain why \ when this occurs. An explicit cast works fine but AS wont even compile.
** How do I get 'AS' functionality in this situation. Namely I need to do a trycast and would prefer not to invoke the exceptionhandler to accomplish it. **
as doesn't work with anything that is a struct. Logically we can understand this because a struct is non nullable by default. The suggestions of casting to object work by cheating and boxing the struct
For example, the following types would give CS0039:
class MyType
{
}
class MyOtherType
{
}
MyOtherType item = new MyOtherType();
var convertedItem = item as MyType;
In the above example, the compiler has determined that given the types participating in the cast, it's impossible to perform the requested conversion.
Here providing conversion operators would solve the problem.
EDIT: working around this error with casting to Object is not recommended, as it defeats the purpose of the type system
If I cast an object in C#, does it still reference the original object cast?
As an example, if I create a method to change an object and then cast that object depending on specific implementation called, does the original object get preserved?
public bool CallChangeString()
{
String str = "hello";
ChangeObject(str);
return String.Equals("HELLO", str);
}
public void ChangeObject(Object obj)
{
String str = obj as String;
str.ToUpper(); // pretend for the sake of this that this changes str to upper case
}
In this case, would the String.Equals return true or false?
Are there any situations where casting would cause the new object to not preserve it's reference?
Depends on what cast you are doing. You can think of two main groups of casting:
Those that preserve identity
Those that don't
Well, thats not very helpful, that is precisely what you are asking.
What casts don't preserve identity? All those that entail a representational change in the object itself, that is, the bits that make up the object change.
Examples? All casts between value types: int to long, int to double, etc., any boxing or unboxing conversion, etc. The bits that make up a long are very different from those that make up an int.
More examples? Any user defined cast operator, explicit or implicit. Why? Because user defined casts that preserve identity are disallowed by the compiler simply because the compiler already does them for you:
class Foo : IFoo
{
public static implicit operator object(Foo foo) => return foo; //Compile time error
public static implicit operator IFoo(Foo foo) => return foo; //compile time error.
public static explicit operator Bar(Foo foo) => return new Bar(foo);
}
Note the general pattern of user defined casts:
any valid operator will always have a new lurking
around in whatever it returns. Thats telling you right away that the
cast can not preserve identity... you are returning a new object.
There is no way you can implement a user defined identity preserving conversion. Thats not a problem because there is no need, those conversions are already provided by C#'s type system.
So, what are identity preserving casts or conversions? Well, those that don't touch the object all; reference conversions.
Huh? But wait, The whole point is that I'm casting the object, how can that be?
In reference conversions you are only "casting" the reference pointing to the object. The object is always the same. This, of course, only makes sense in reference types and that is why value types don't have identity preserving conversions; there are no references to value types unless they are boxed.
Examples? object to string, Foo to IFoo, Giraffe to Animal, etc.
Do note that reference types can very well implement user defined casts too, but these will not preserve identity.
All that said, this is the rule of the thumb:
Any cast provided/allowed by the language type system itself preserves identity. These are, exclusively, reference conversions and only apply to reference types.
Any user defined cast, explicit or implicit, does not preserve identity (rememeber, (long)2 is a user defined cast, somebody had to implement it in the class System.Int64).
So, answering your question, var str = obj as string is a reference conversion, which means that ReferenceEquals(str, obj) is true; str and obj point to exactly the same object, the only difference is the type of the reference.
strings are immutable, so you can't change them. However you can create new instances:
myString = myString.Replace("", ".");
Be aware that myString is a completely new instance which is not related to the original string. Thus even if you assign something different to myString this won't affect your calling code that relies on the original instance.
In your example str.ToUpper() won't change anything, as ToUpper returns a new string instead of changing the current (str) instance.
casting creates a new reference to the same instance. Thus modifications to an instance are reflected in all of its references, be it casted instances or just re-references
var a = (MyType) myInstance;
a.MyProperty = 4;
After the last statement both a and myInstance have the property MyProperty set to 4, because both variables a and myInstance reference the same instance of MyType.
Change your method like this and see result )
public bool CallChangeString()
{
String str = "hello";
ChangeObject(str);
return String.Equals("HELLO", str);
}
This question already has answers here:
Direct casting vs 'as' operator?
(16 answers)
Difference between is and as keyword
(13 answers)
Closed 7 years ago.
Which method is best practice to type casting and checking ?
Employee e = o as Employee;
if(e != null)
{
//DO stuff
}
OR
if(o is Employee)
{
Employee e = (Employee) o;
//DO stuff
}
At least there are two possibilities for casting, one for type checking and a combination of both called pattern matching. Each has its own purpose and it depends on the situation:
Hard cast
var myObject = (MyType)source;
You normally do that if you are absolutely sure if the given object is of that type. A situation where you use it, if you subscribed to an event handler and you cast the sender object to the correct type to work on that.
private void OnButtonClick(object sender, EventArgs e)
{
var button = (Button)sender;
button.Text = "Disabled";
button.Enabled = false;
}
Soft cast
var myObject = source as MyType;
if (myObject != null)
// Do Something
This will normally be used if you can't know if you really got this kind of type. So simply try to cast it and if it is not possible, simply give a null back. A common example would be if you have to do something only if some interface is fullfilled:
var disposable = source as IDisposable;
if(disposable != null)
disposable.Dispose();
Also the as operator can't be used on a struct. This is simply because the operator wants to return a null in case the cast fails and a struct can never be null.
Type check
var isMyType = source is MyType;
This is rarely correctly used. This type check is only useful if you only need to know if something is of a specific type, but you don't have to use that object.
if(source is MyType)
DoSomething();
else
DoSomethingElse();
Pattern matching
if (source is MyType myType)
DoSomething(myType);
Pattern matching is the latest feature within the dotnet framework that is relevant to casts. But you can also handle more complicated cases by using the switch statement and the when clause:
switch (source)
{
case SpecialType s when s.SpecialValue > 5
DoSomething(s);
case AnotherType a when a.Foo == "Hello"
SomethingElse(a);
}
I think this is a good question, that deserves a serious and detailed answer. Type casts is C# are a lot of different things actually.
Unlike C#, languages like C++ are very strict about these, so I'll use the naming there as reference. I always think it's best to understand how things work, so I'll break it all down here for you with the details. Here goes:
Dynamic casts and static casts
C# has value types and reference types. Reference types always follow an inheritance chain, starting with Object.
Basically if you do (Foo)myObject, you're actually doing a dynamic cast, and if you're doing (object)myFoo (or simply object o = myFoo) you're doing a static cast.
A dynamic cast requires you to do a type check, that is, the runtime will check if the object you are casting to will be of the type. After all, you're casting down the inheritance tree, so you might as well cast to something else completely. If this is the case, you'll end up with an InvalidCastException. Because of this, dynamic casts require runtime type information (e.g. it requires the runtime to know what object has what type).
A static cast doesn't require a type check. In this case we're casting up in the inheritance tree, so we already know that the type cast will succeed. No exception will be thrown, ever.
Value type casts are a special type of cast that converts different value types (f.ex. from float to int). I'll get into that later.
As, is, cast
In IL, the only things that are supported are castclass (cast) and isinst (as). The is operator is implemented as a as with a null check, and is nothing more than a convenient shorthand notation for the combination of them both. In C#, you could write is as: (myObject as MyFoo) != null.
as simply checks if an object is of a specific type and returns null if it's not. For the static cast case, we can determine this compile-time, for the dynamic cast case we have to check this at runtime.
(...) casts again check if the type is correct, and throw an exception if it's not. It's basically the same as as, but with a throw instead of a null result. This might make you wonder why as is not implemented as an exception handler -- well, that's probably because exceptions are relatively slow.
Boxing
A special type of cast happens when you box a value type into an object. What basically happens is that the .NET runtime copies your value type on the heap (with some type information) and returns the address as a reference type. In other words: it converts a value type to a reference type.
This happens when you have code like this:
int n = 5;
object o = n; // boxes n
int m = (int)o; // unboxes o
Unboxing requires you to specify a type. During the unboxing operation, the type is checked (like the dynamic cast case, but it's much simpler because the inheritance chain of a value type is trivial) and if the type matches, the value is copied back on the stack.
You might expect value type casts to be implicit for boxing -- well, because of the above they're not. The only unboxing operation that's allowed, is the unboxing to the exact value type. In other words:
sbyte m2 = (sbyte)o; // throws an error
Value type casts
If you're casting a float to an int, you're basically converting the value. For the basic types (IntPtr, (u)int 8/16/32/64, float, double) these conversions are pre-defined in IL as conv_* instructions, which are the equivalent of bit casts (int8 -> int16), truncation (int16 -> int8), and conversion (float -> int32).
There are some funny things going on here by the ways. The runtime seems to work on multitudes of 32-bit values on the stack, so you need conversions even on places where you wouldn't expect them. For example, consider:
sbyte sum = (sbyte)(sbyte1 + sbyte2); // requires a cast. Return type is int32!
int sum = int1 + int2; // no cast required, return type is int32.
Sign extension might be tricky to wrap your head around. Computers store signed integer values as 1-complements. In hex notation, int8, this means that the value -1 is 0xFF. So what happens if we cast it to an int32? Again, the 1-complement value of -1 is 0xFFFFFFFF - so we need to propagate the most significant bit to the rest of 'added' bits. If we're doing unsigned extensions, we need to propagate zero's.
To illustrate this point, here's a simple test case:
byte b1 = 0xFF;
sbyte b2 = (sbyte)b1;
Console.WriteLine((int)b1);
Console.WriteLine((int)b2);
Console.ReadLine();
The first cast to int is here zero extended, the second cast to int is sign extended. You also might want to play with the "x8" format string to get the hex output.
For the exact difference between bit casts, truncation and conversion, I refer to the LLVM documentation that explains the differences. Look for sext/zext/bitcast/fptosi and all the variants.
Implicit type conversion
One other category remains, and that's the conversion operators. MSDN details how you can overload the conversion operators. Basically what you can do is implement your own conversion, by overloading an operator. If you want the user to explicitly specify that you intend to cast, you add the explicit keyword; if you want implicit conversions to happen automagically, you add implicit. Basically you'll get:
public static implicit operator byte(Digit d) // implicit digit to byte conversion operator
{
return d.value; // implicit conversion
}
... after which you can do stuff like
Digit d = new Digit(123);
byte b = d;
Best practices
First off, understand the differences, which means implementing small test programs until you understand the distinction between all of the above. There's no surrogate for understanding How Stuff Works.
Then, I'd stick to these practices:
The shorthands are there for a reason. Use the notation that's the shortest, it's probably the best one.
Don't use casts for static casts; only use casts for dynamic casts.
Only use boxing if you need it. The details of this go well beyond this answer; basically what I'm saying is: use the correct type, don't wrap everything.
Notice compiler warnings about implicit conversions (f.ex. unsigned/signed) and always resolve them with explicit casts. You don't want to get surprises with strange values due to sign/zero extension.
In my opinion, unless you know exactly what you're doing, it's best to simply avoid the implicit/explicit conversion -- a simple method call is usually better. The reason for this is that you might end up with an exception on the loose, that you didn't see coming.
With the second method, if the cast fails an exception is thrown.
When casting using as, you can only use reference types. so if you are typecasting to a value type, you must still use int e = (int) o; method.
a good rule of thumb, is : if you can assign null as a value to the object, you can type cast using as.
that said, null comparison is faster than throwing and catching an exception, so in most cases, using as should be faster.
I can't honestly say with certainty if this applies with your is check in place though. It could fail under some multi threading conditions where another thread changes the object you're casting.
I would use the as (safe-cast) operator if I need to use the object after casting. Then I check for null and work with the instance. This method is more efficient than is + explicit cast
In general, the as operator is more efficient because it actually returns the cast value if the cast can be made successfully. The is operator returns only a Boolean value. It can therefore be used when you just want to determine an object's type but do not have to actually cast it.
(more information here).
I am not sure about it but I think that is is using as under the hood and just returns if the object after casting is null (in case of reference types) / an exception was thrown (in case of value types) or not.
Well, it's a matter of taste and specifics of problem that you're dealing with. Let's have a look at two examples with generic methods.
For generic method with 'class' constraint (the safest approach with double cast):
public void MyMethod<T>(T myParameter) where T : class
{
if(myParameter is Employee)
{
// we can use 'as' operator because T is class
Employee e = myParameter as Employee;
//DO stuff
}
}
Also you can do someting like this (one cast operation here but defined variable of type that may or may not be correct) :
public void MyMethod<T>(T myParameter) where T : class
{
Employee e;
if((e = myParameter as Employee) != null)
{
//DO stuff with e
}
}
For generic method with 'struct' constraint :
public void MyMethod<T>(T myParameter) where T : struct
{
if(myParameter is int)
{
// we cant use 'as' operator here because ValueType cannot be null
// explicit conversion doesn't work either because T could be anything so :
int e = Convert.ToInt32(myParameter);
//DO stuff
}
}
Simple scenario with explicit cast:
int i = 5;
object o = (object)i; // boxing
int i2 = (int)o; // unboxing
We can use explicit cast here because we are 100% sure of what types do we use.
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 '
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.