I read that casting will throw an exception if the cast doesn't go through and that there's a better syntax to cast which return a null instead of an exception if the cast is not possible. But I forgot it. Any refresher?
thanks.
I think you are referring to the as cast. However as cannot be used on non-reference types so you cannot do int x = obj as int.
In order to parse an int or some other value-type you can use the type specific trycast methods..
int x;
bool success = int.TryParse(someString, out x);
I believe this is what you're looking for...
string s = "36";
int resultInt;
int.TryParse(s, out resultInt);
if it's originating from a string, you can always use a TryParse()
if(!Int.TryParse(s, out i))
(handle non-int code here)
In c# if you use int x = Convert.toInt32(string) it internally calls int.tryparse as the convert method is a static wrapper class for tryparse. I find it a bit cleaner to use, though it is in theory a bit slower.
You can use the "as" operator on reference types. But since an int can be null, you can't use that operator. So for a string object to string cast you could do this:
object o = "";
string s = o as string;
But couldn't do the same with an int.
What your looking for is the as
So int myCasted = myVar as int;
Which apparently won't work on non-nullable value types
Related
Consider the following code:
void Handler(object o, EventArgs e)
{
// I swear o is a string
string s = (string)o; // 1
//-OR-
string s = o as string; // 2
// -OR-
string s = o.ToString(); // 3
}
What is the difference between the three types of casting (okay, the 3rd one is not a casting, but you get the intent). Which one should be preferred?
string s = (string)o; // 1
Throws InvalidCastException if o is not a string. Otherwise, assigns o to s, even if o is null.
string s = o as string; // 2
Assigns null to s if o is not a string or if o is null. For this reason, you cannot use it with value types (the operator could never return null in that case). Otherwise, assigns o to s.
string s = o.ToString(); // 3
Causes a NullReferenceException if o is null. Assigns whatever o.ToString() returns to s, no matter what type o is.
Use 1 for most conversions - it's simple and straightforward. I tend to almost never use 2 since if something is not the right type, I usually expect an exception to occur. I have only seen a need for this return-null type of functionality with badly designed libraries which use error codes (e.g. return null = error, instead of using exceptions).
3 is not a cast and is just a method invocation. Use it for when you need the string representation of a non-string object.
string s = (string)o; Use when something should
definitely be the other thing.
string s = o as string; Use when something might be the other
thing.
string s = o.ToString(); Use when you don't care what
it is but you just want to use the
available string representation.
It really depends on whether you know if o is a string and what you want to do with it. If your comment means that o really really is a string, I'd prefer the straight (string)o cast - it's unlikely to fail.
The biggest advantage of using the straight cast is that when it fails, you get an InvalidCastException, which tells you pretty much what went wrong.
With the as operator, if o isn't a string, s is set to null, which is handy if you're unsure and want to test s:
string s = o as string;
if ( s == null )
{
// well that's not good!
gotoPlanB();
}
However, if you don't perform that test, you'll use s later and have a NullReferenceException thrown. These tend to be more common and a lot harder to track down once they happens out in the wild, as nearly every line dereferences a variable and may throw one. On the other hand, if you're trying to cast to a value type (any primitive, or structs such as DateTime), you have to use the straight cast - the as won't work.
In the special case of converting to a string, every object has a ToString, so your third method may be okay if o isn't null and you think the ToString method might do what you want.
'as' is based on 'is', which is a keyword that checks at runtime if the object is polimorphycally compatible (basically if a cast can be made) and returns null if the check fails.
These two are equivalent:
Using 'as':
string s = o as string;
Using 'is':
if(o is string)
s = o;
else
s = null;
On the contrary, the c-style cast is made also at runtime, but throws an exception if the cast cannot be made.
Just to add an important fact:
The 'as' keyword only works with reference types. You cannot do:
// I swear i is an int
int number = i as int;
In those cases you have to use casting.
If you already know what type it can cast to, use a C-style cast:
var o = (string) iKnowThisIsAString;
Note that only with a C-style cast can you perform explicit type coercion.
If you don't know whether it's the desired type and you're going to use it if it is, use as keyword:
var s = o as string;
if (s != null) return s.Replace("_","-");
//or for early return:
if (s==null) return;
Note that as will not call any type conversion operators. It will only be non-null if the object is not null and natively of the specified type.
Use ToString() to get a human-readable string representation of any object, even if it can't cast to string.
The as keyword is good in asp.net when you use the FindControl method.
Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
...
}
This means you can operate on the typed variable rather then having to then cast it from object like you would with a direct cast:
object linkObj = this.FindControl("linkid");
if (link != null)
{
Hyperlink link = (Hyperlink)linkObj;
}
It's not a huge thing, but it saves lines of code and variable assignment, plus it's more readable
According to experiments run on this page: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as
(this page is having some "illegal referrer" errors show up sometimes, so just refresh if it does)
Conclusion is, the "as" operator is normally faster than a cast. Sometimes by many times faster, sometimes just barely faster.
I peronsonally thing "as" is also more readable.
So, since it is both faster and "safer" (wont throw exception), and possibly easier to read, I recommend using "as" all the time.
2 is useful for casting to a derived type.
Suppose a is an Animal:
b = a as Badger;
c = a as Cow;
if (b != null)
b.EatSnails();
else if (c != null)
c.EatGrass();
will get a fed with a minimum of casts.
"(string)o" will result in an InvalidCastException as there's no direct cast.
"o as string" will result in s being a null reference, rather than an exception being thrown.
"o.ToString()" isn't a cast of any sort per-se, it's a method that's implemented by object, and thus in one way or another, by every class in .net that "does something" with the instance of the class it's called on and returns a string.
Don't forget that for converting to string, there's also Convert.ToString(someType instanceOfThatType) where someType is one of a set of types, essentially the frameworks base types.
It seems the two of them are conceptually different.
Direct Casting
Types don't have to be strictly related. It comes in all types of flavors.
Custom implicit/explicit casting: Usually a new object is created.
Value Type Implicit: Copy without losing information.
Value Type Explicit: Copy and information might be lost.
IS-A relationship: Change reference type, otherwise throws exception.
Same type: 'Casting is redundant'.
It feels like the object is going to be converted into something else.
AS operator
Types have a direct relationship. As in:
Reference Types: IS-A relationship Objects are always the same, just the reference changes.
Value Types: Copy boxing and nullable types.
It feels like the you are going to handle the object in a different way.
Samples and IL
class TypeA
{
public int value;
}
class TypeB
{
public int number;
public static explicit operator TypeB(TypeA v)
{
return new TypeB() { number = v.value };
}
}
class TypeC : TypeB { }
interface IFoo { }
class TypeD : TypeA, IFoo { }
void Run()
{
TypeA customTypeA = new TypeD() { value = 10 };
long longValue = long.MaxValue;
int intValue = int.MaxValue;
// Casting
TypeB typeB = (TypeB)customTypeA; // custom explicit casting -- IL: call class ConsoleApp1.Program/TypeB ConsoleApp1.Program/TypeB::op_Explicit(class ConsoleApp1.Program/TypeA)
IFoo foo = (IFoo)customTypeA; // is-a reference -- IL: castclass ConsoleApp1.Program/IFoo
int loseValue = (int)longValue; // explicit -- IL: conv.i4
long dontLose = intValue; // implict -- IL: conv.i8
// AS
int? wraps = intValue as int?; // nullable wrapper -- IL: call instance void valuetype [System.Runtime]System.Nullable`1<int32>::.ctor(!0)
object o1 = intValue as object; // box -- IL: box [System.Runtime]System.Int32
TypeD d1 = customTypeA as TypeD; // reference conversion -- IL: isinst ConsoleApp1.Program/TypeD
IFoo f1 = customTypeA as IFoo; // reference conversion -- IL: isinst ConsoleApp1.Program/IFoo
//TypeC d = customTypeA as TypeC; // wouldn't compile
}
All given answers are good, if i might add something:
To directly use string's methods and properties (e.g. ToLower) you can't write:
(string)o.ToLower(); // won't compile
you can only write:
((string)o).ToLower();
but you could write instead:
(o as string).ToLower();
The as option is more readable (at least to my opinion).
string s = o as string; // 2
Is prefered, as it avoids the performance penalty of double casting.
I would like to attract attention to the following specifics of the as operator:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/as
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.
Use direct cast string s = (string) o; if in the logical context of your app string is the only valid type. With this approach, you will get InvalidCastException and implement the principle of Fail-fast. Your logic will be protected from passing the invalid type further or get NullReferenceException if used as operator.
If the logic expects several different types cast string s = o as string; and check it on null or use is operator.
New cool feature have appeared in C# 7.0 to simplify cast and check is a Pattern matching:
if(o is string s)
{
// Use string variable s
}
or
switch (o)
{
case int i:
// Use int variable i
break;
case string s:
// Use string variable s
break;
}
When trying to get the string representation of anything (of any type) that could potentially be null, I prefer the below line of code. It's compact, it invokes ToString(), and it correctly handles nulls. If o is null, s will contain String.Empty.
String s = String.Concat(o);
Since nobody mentioned it, the closest to instanceOf to Java by keyword is this:
obj.GetType().IsInstanceOfType(otherObj)
What is the big difference between parsing and typecasting?
I try to use type casting to a string and it gives me error.
Something like this:
string str = "10";
int i = (int) str;
For type casting to work the types need to be compatible:
object str = 10;
int i = (int) str;
Parsing is conversion between different types:
string str = "10";
int i = int.Parse(str);
Casting works when the objects share some piece of inheritance. But in your case
int i = (int) str;
You are dealing with implicit automatic conversion. In which the compiler will automatically widden/losen a .NET built-in type. For a complete guide go here and look for Converting and Casting
Int32.Parse(...
Parsing is for when they are two unrelated objects, but there is a way of converting one way to another.
Which (if any) is more correct? Why?
string someVariable = (string) someOtherVariable;
string someVariable = someOtherVariable.ToString();
string someVariable = someOtherVariable as string;
I've used all three, but I don't have any preference or understanding why one is better than the other.
These are not all examples of casting.
This is a cast:
string someVariable = (string) someOtherVariable;
This is method call:
string someVariable = someOtherVariable.ToString();
And this is a safe cast:
string someVariable = someOtherVariable as string;
The first and third examples are actual casts. The first cast has the potential to throw an InvalidCastException whereas the third example will not throw that exception. That is why the as operator is known as a safe cast.
Here's my article on the subject.
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
As for which one is "most correct", the one that is most correct is the one that has the meaning you intend to convey to the reader of the program.
"ToString()" conveys "this is probably not a string; if it is not, then I wish to obtain from the object a string which represents it."
The "cast" operator conveys either "this is a string, and I am willing to have my program crash if I am wrong", or the opposite, "this is not a string and I want to call a user-defined conversion on this object to string".
The "as" operator conveys "this might be a string and if it isn't, I want the result to be null."
Which of those four things do you mean?
The three do different things -- none are "more correct", it depends on your situation. If you have a bunch of objects that may not be strings, you'd probably use .ToString() (with a null check, if you expect nulls).
If you only care about the non-null strings, but still expect to be receiving non-strings, use an "as" cast, and then ignore the values that come in as null (they were either originally null, or of a non-string type)
if you expect to receive only strings, it is best to use the (string) cast. This expresses the intent best in the code.
object foo = 5;
string str = (string)foo; // exception
string str = foo as string; // null
string str = foo.ToString(); // "5"
object foo = "bar";
string str = (string)foo; // "bar"
string str = foo as string; // "bar"
string str = foo.ToString(); // "bar"
object foo = null;
string str = (string)foo; // null
string str = foo as string; // null
string str = foo.ToString(); // exception
The as keyword is very useful if you think the conversion will fail during an upcast. For instance, if I want to perform the same operation on similar types in a Control list... let's say unchecking all Checkboxes:
foreach (Control ctrl in Controls)
{
Checkbox box = ctrl as Checkbox;
if (box != null)
box.Checked = false;
}
This way, if my list has something else, like a text box or a label, no exception is thrown (as simply sets the variable = null if it fails), and it's very efficient. There is no exception overhead.
The ideas of CAST and CONVERT should not be confused here. Casting involves viewing an object as if it was another type. Converting involves transforming an object to another type.
If your intention is to CAST to a string, you should use the first or third. (Option depends on what you want to happen in the error condition. See bangoker's answer.)
If your intention is to CONVERT to a string, you should use the second. (Or better, ChaosPandion's modified statement with the trinary operator.) That is because the ToString method's behaviour is defined as converting the object into a string representation.
This is 100% personal preference here, but for me I use the folowing:
string someVariable = (string) someOtherVariable;
When converting to a child or parent type (eg. NetworkStream->Stream)
string someVariable = someOtherVariable.ToString();
When converting to a new type (int -> string)
And I never use the latter (as string) method, mostly because coming from a C/C++ background I prefer the() and it's a bit more concise.
There is a big difference between casting with parenthesis and casting with "as".
Basically, parenthesis will thrown an exception while "as" will return null instead of raising an exception.
More detailed info here
string someVariable = (string) someOtherVariable;
this is your good old normal casting and it will throw an exception if you try to cast something into something it CANNOT be casted (thus some times you need to check if they are castable)
string someVariable = someOtherVariable.ToString();
is not really casting, its executing a method that may come from different places(interfaces) but that ALL objects in C# have, since they inherit from the Object object, which has it. It has a default operation which is giving the name of the type of the object, but you can overload it to print whatever you want your class to print on the ToString method.
string someVariable = someOtherVariable as string;
This is a new c# casting, it will check first if it is castable by using a variable is string first and then doing the casting if it is valid or return null if it is not, so it could be a silent error if you are expecting exceptions, since you should check against null.
Basically
myType as myOtherType
is the same as:
var something = null;
if(myType is myOtherType)
{
something = (myType) myotherType;
}
except that as will check and cast in one step, and not in 2.
First of all, you should avoid casting with AS operator. The article linked explains why.
Second, you can use AS operator ONLY if you expect the value not being of the type you cast too. So you will have to check that manually.
Also the obj.ToString() method call is not a casting, it converts object to a string representation (which in case of a string itself is the same string). This can be ovveridden by any class.
So as a general rule I follow this:
Always use (Type) casting.
Use as operator only if object can be of other type than you cast to.
If using as operator - ALWAYS check the result for NULL.
UseToString only in cases when you need to display information about the object.
If your question about the best practice for syntax in casting a variable, then I prefer to use next one:
var someVariable = someOtherVariable as string ?? string.Empty;
Off course you can use someVariableDefaultValue instead of string.Empty.
In case if you cast not to string but into the some complex type, then I recommend next syntax, sometimes called the Safe Navigation Operator:
var complexVariable = otherComplexVariable as ComplexType;
if (complexVariable?.IsCondition)
{
//your code if cast passed and IsCondition is true
}
else
{
//your code if cast not passed or IsCondition is false
}
C# accepts the following:
object o = "hello";
int? i = o as int?;
if (i == null) {
// o was not a boxed int
}
else {
// Can use i.Value to recover the original boxed value
}
But not
String o = "hello";
int? i = o as int?;
if (i == null) {
// o was not a boxed int
}
else {
// Can use i.Value to recover the original boxed value
}
I'm just wondering about the behaviour of the keyword as in C#.
The same as in Java this would fail:
Object test1 = "hello";
Integer test2 = (Integer) test1;
String test3 = "hello";
Integer test4 = (Integer) test3; //compilation error
The compiler knows that a string can never be an int? so it tells you that. That doesn't mean that int? isn't useful. Your attempted use case is far from the normal one. The normal one is "I want to represent an integer and the possibility that the value is missing/unknown". For that, int? works extremely well.
Why would you expect your original code to work? Why would it be helpful?
Note that you can use as with nullable types, for unboxing:
object o = "hello";
int? i = o as int?;
if (i == null)
{
// o was not a boxed int
}
else
{
// Can use i.Value to recover the original boxed value
}
EDIT: Having seen your comment, you don't use as to parse things. You probably want to use int.TryParse:
string text = "123":
int value;
if (int.TryParse(text, out value))
{
Console.WriteLine("Parsed successfully: {0}", value);
}
else
{
Console.WriteLine("Unable to parse text as an integer");
}
If you're sure the string is meant to be an integer (i.e. it's a bug otherwise) then you can just use int.Parse:
int value = int.Parse(text);
That will throw an exception if the parsing fails.
Note also that both of these methods allows you to specify a format provider (usually a culture info) which allows you to express how numbers are expressed in that format (e.g. thousands separators).
EDIT: In answer to your new question, the compiler prevents this because it knows a string can't possibly be a boxed int - the conversion will never ever succeed. When it only knows that the original value is an object, it might succeed.
For instance, suppose I said to you, "Here's a shape: is it a square?" That's a sensible question. It's reasonable to ask it: you can't tell without looking at the shape.
If, however, I said: "Here's a triangle: is it a square?" Then you'd be reasonably entitled to laugh in my face, as a triangle can't possibly be a square - the question doesn't make sense.
int? means a nullable integer type, not an int that could contain any other type of variable.
If you want a variable type that could contain an int or a string, you'd have to use an object, or a string I suppose, and then live a life filled with type casting. I don't know why you would want to do that, though.
int? allows you to store any integer value, or a null value. Which is useful when say the answer to the question "How many orders has this person placed" is legitimately "I don't know" instead of a number of orders, or zero which would be "I know for a fact this person has never placed an order".
I want to add some further information.
An other case, why the cast is invalid and the compiler throws an error on compilation is, that System.String is marked as sealed. So the compiler knows from which types System.String inherites and to which types you can cast the string using the as-operator.
Due to the keyword sealed, the compiler also knows that you cannot inherit from System.String to add functionality or implement some additional interfaces.
The code below is an example and the compiler will throw the following error on compilation
Cannot convert type 'SealedClass' to
'ICastToInterface' via a reference
conversion, boxing conversion,
unboxing conversion, wrapping
conversion, or null type conversion
public class UnsealedClass {
// some code
}
public sealed class SealedClass {
// some code
}
public interface ICastToInterface {
// some code
}
public class Test {
public Test() {
UnsealedClass unsealedClass = new UnsealedClass();
SealedClass sealedClass = new SealedClass();
ICastToInterface unsealedCast = unsealedClass as ICastToInterface; // This works fine
ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed
}
}
but you can check the value of null and set it to null.
int? blah;
if (blah == null)
{}
int? is a nullable integer, it has nothing to do with casting and the as keyword. "String" is a string type object, which is not convertible to an int (nullable or non-nullable).
The as Keyword is virtually the same as casting using brackets except it will not return an error, it will set the object to null:
int i = 1;
object o = i; //boxing
int j = (int)o; //unboxing
This first example works as the object assigned to o is an int.
Now consider:
string i = "MyString";
object o = MyString;
int j = (int)o //unboxing raises exception
int j = o as int; //raises compilation Error as int is not nullable
int? j = o as int?; /// o == null
I hope that that helps to explain the difference between the two concepts.
Richard
This is probably trivial, but I can't think of a better way to do it. I have a COM object that returns a variant which becomes an object in C#. The only way I can get this into an int is
int test = int.Parse(string.Format("{0}", myobject))
Is there a cleaner way to do this? Thanks
You have several options:
(int) — Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.
int.Parse()/int.TryParse() — For converting from a string of unknown format.
int.ParseExact()/int.TryParseExact() — For converting from a string in a specific format
Convert.ToInt32() — For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.
as int? — Note the "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null rather than throwing an exception if the conversion fails.
Of these, I would prefer (int) if the object really is just a boxed integer. Otherwise use Convert.ToInt32() in this case.
Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails (int)(short) might work instead, and for recommending you check your debugger to find out the actual runtime type.
The cast (int) myobject should just work.
If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.
When doing a cast on a boxed value type it is only valid to cast it to the type boxed.
Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.
Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)
Convert.ToInt32(myobject);
This will handle the case where myobject is null and return 0, instead of throwing an exception.
Use Int32.TryParse as follows.
int test;
bool result = Int32.TryParse(value, out test);
if (result)
{
Console.WriteLine("Sucess");
}
else
{
if (value == null) value = "";
Console.WriteLine("Failure");
}
Maybe Convert.ToInt32.
Watch out for exception, in both cases.
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
I am listing the difference in each of the casting ways. What a particular type of casting handles and it doesn't?
// object to int
// does not handle null
// does not handle NAN ("102art54")
// convert value to integar
int intObj = (int)obj;
// handles only null or number
int? nullableIntObj = (int?)obj; // null
Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null
// best way for casting from object to nullable int
// handles null
// handles other datatypes gives null("sadfsdf") // result null
int? nullableIntObj2 = obj as int?;
// string to int
// does not handle null( throws exception)
// does not string NAN ("102art54") (throws exception)
// converts string to int ("26236")
// accepts string value
int iVal3 = int.Parse("10120"); // throws exception value cannot be null;
// handles null converts null to 0
// does not handle NAN ("102art54") (throws exception)
// converts obj to int ("26236")
int val4 = Convert.ToInt32("10120");
// handle null converts null to 0
// handle NAN ("101art54") converts null to 0
// convert string to int ("26236")
int number;
bool result = int.TryParse(value, out number);
if (result)
{
// converted value
}
else
{
// number o/p = 0
}
There's also TryParse.
From MSDN:
private static void TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
if (value == null) value = "";
Console.WriteLine("Attempted conversion of '{0}' failed.", value);
}
}
Strange, but the accepted answer seems wrong about the cast and the Convert in the mean that from my tests and reading the documentation too it should not take into account implicit or explicit operators.
So, if I have a variable of type object and the "boxed" class has some implicit operators defined they won't work.
Instead another simple way, but really performance costing is to cast before in dynamic.
(int)(dynamic)myObject.
You can try it in the Interactive window of VS.
public class Test
{
public static implicit operator int(Test v)
{
return 12;
}
}
(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass
You can first cast object to string and then cast the string to int;
for example:
string str_myobject = myobject.ToString();
int int_myobject = int.Parse(str_myobject);
this worked for me.
int i = myObject.myField.CastTo<int>();
This worked for me, returning 0 also when myobject contains a DBNull
int i = myobject.ToString().Cast<int>().FirstOrDefault();