views:

311

answers:

3

I am trying to get a difference between the type casting methods.

eg.

Method 1

public byte fun()
{
   object value=1;
   return (byte)value; // this gives me error
}

Method 2

public byte fun()
{
   object value=1;
   return byte.Parse(value.ToString()); // this runs 
}

Method 3

public byte fun()
{
   object value=1;
   return Convert.ToByte(value); // this runs
}

What is the difference between all the three. How they are working internally. What are value type and refrence type here. Which function can convert value type to ref type and vice versa

Edit 2

When i writes this line what datatype '1' will be treated by default int32, byte or something else.

object value=1;

+5  A: 

There are a lot of questions here.

Method 1 fails because you cannot do an unbox and a cast in a single operation. You're setting "value" to a boxed integer. When you try to do the cast, you're unboxing the integer and trying to cast to a byte in a single operation, which fails. This does work, btw:

return (byte)( (int)value) ); // Unbox, then cast, in two operations

Method 2 works because you're converting the integer to a string, then using byte.Parse to convert it to a byte. This is very expensive, since it's going to/from strings.

Method 3 works because it sees that the object in value is IConvertible (int), and uses the appropriate conversion operation to convert to byte. This is probably a more efficient way of approaching it, in this case. Since "value" is storing an int, and int supports IConvertible, Convert.ToByte will basically do a null check, then call Convert.ToByte(int), which is quite fast (it does bounds checking, and a direct cast).

I'd recommend reading Eric Lippert's blog post titled Representation and Identity. It covers casting in detail, and explains why method 1 fails...

Reed Copsey
+1  A: 
// This is a direct cast. It expects that the object
// in question is already allocated as the data type
// indicated in the cast
(byte)value;

// This is a direct code conversion. It takes the argument
// and runs through code to create a new variable of the
// type byte. You'll notice if you include this in different
// code that value will still be an object but your new
// data will be a byte type
byte.Parse(value.ToString());

// This will convert any object similarly to the byte.Parse.
// It is not as fast because it does not have a definitely
// typed parameter (as parse has string). So it must go 
// through a couple of extra steps to guarantee the conversion
// is smooth.
Convert.ToByte(value);

Direct casting is always the fastest. It assumes the type is already established and allocated so all it has to do is switch its reference type in memory. The conversion methods are code conversions so they require a little more time. I don't know the benchmarks, but Parse is slightly faster because it deals with a specific in and a specific out (string->byte). Convert is the slowest of the conversion methods because it lacks this same specificity.

Joel Etherton
His method one isn't a direct cast, however... it's an unbox + cast, which will fail.
Reed Copsey
Also, Convert is faster, since it can use int.ToByte (from IConvertible.ToByte) directly.
Reed Copsey
@Reed Copsey: It would be unboxing if it was originally instantiated as a byte. It wasn't, it began it's allocation as an object. In order for it be "unboxed", it must first be boxed from byte to object. In this instance it's a direct conversion and that's why it fails. See: http://msdn.microsoft.com/en-us/library/b95fkada(VS.80).aspx and http://msdn.microsoft.com/en-us/library/ms173105(VS.80).aspx
Joel Etherton
@Joel: No. It's instantiated as an Int32, since that's the default integer literal. That Int32 is boxed into an object "value". When you try to cast this to a byte, it's unboxing the int, and trying to cast in one operation, which gives you a runtime error (InvalidCastException). See: http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
Reed Copsey
A: 

Well here is my shot at it:

Method 1

This is a type cast, i.e. the value has to be of a type that can be implcitly or explicitly converted into a byte. Furthermore, value must not be outside the bounds of a byte.

The call fails as the compiler does not have any information what type of object it should cast from, and thus cannot perform a implicit or explicit conversion. Doing

int obj = 1;
byte b = (byte) obj; 

or

byte b = (byte) (int) obj;

works. The second option uses expicit unboxing (thus providing the needed information) as described in Reed Copsey's comment and post. The link provided by Reed Copsey's comment explains this in detail.

For custom objects casts use the implicit and explicit conversions are operators which are static methods defined on the class. For object no implicit or explicit operations exist (see link forthe reason why), while for int these operations exist.

Method 2

Here you are parsing a string the value of the string has to be a number that is inside the bound of a byte. Here you could also use TryParse which allows you to check whether the conversion will succeed.

Method 3

Uses type conversion of the Convert class. This is the most flexible method that supports most of the common types. Here, the value must be convertible to a numer, and the value must be inside the bounds of the byte. The Convert class uses IConvertible to convert between the different types and, therefore, is extensible.

Obalix
Your "Method 1" explanation is incorrect. This is a specific restriction on unboxing -ie: unboxing a type T can only be unboxed to T directly. See: http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
Reed Copsey
Not sure whether that link contradicts my statement ... I guess that `int jjj = (int) (short) ooo;` is the statement you have in mind. As I interpret it it is the equivalent to `short s = (short) ooo; int i = (int) short;`. And this behaviour would be consistent with what I wrote.
Obalix
It's not a matter of the compiler "not having any information about what type of object should be cast", but rather that the type differs when you're unboxing, and you can't unbox+cast in one operation.
Reed Copsey
@Reed Copsey: I just read the document you posted and see what you mean. Therefore, I edited my answer to be a bit more precise.
Obalix
Also - casting is not an operator, though - it's part of the language specification...
Reed Copsey
Never said anything else ... it uses the implicit and explicit type conversions though, al least for non-intrinsic types. So I assume that there is a similar concept for intrinsic types.
Obalix