casting vs. using the "Convert" methods?

  • Thread starter Thread starter Jim Bancroft
  • Start date Start date
J

Jim Bancroft

Hi everyone,

A basic one here, I think. I haven't found the pattern yet, but
sometimes when I cast a variable to another type using the "C" style cast
operator the compiler refuses to play along. It says it's an invalid cast.
However, if I use the Convert.ToInt32() method (for example) things will
work. At least, that's how it appears to me.

Could someone explain when to use old-style parenthesized casts vs. the
Convert() methods?
 
For the most part, casting says "This object of type A is really an
object of type B-derived-from-A"
Convert.To*() functions say This object isn't a type B, but there exists
a way to convert to type B"

string a = "1234";
object b = a;
string c = (string) b; // succeeds because b really
is a string.
// int d = (int) b; // fails because b is not an int.
int e = Convert.ToInt32(b); // Succeeds because b can be converted
into an int.
 
Jim said:
Hi everyone,

A basic one here, I think. I haven't found the pattern yet, but
sometimes when I cast a variable to another type using the "C" style cast
operator the compiler refuses to play along. It says it's an invalid cast.
However, if I use the Convert.ToInt32() method (for example) things will
work. At least, that's how it appears to me.

Could someone explain when to use old-style parenthesized casts vs. the
Convert() methods?

Basically, a cast does not really convert anything but only tells the
compiler to treat something as something "similar" - it just gets a
different internal type label, seen from the compiler's standpoint.
Converting data usually actually changes the underlying data structure,
casting does not do this.

Alexander
 
Not true. The truth is a bit more complex than that. .NET provides
three methods of getting from point A to point B, as it were.

First, there is the implicit cast. This is the cast that doesn't
require you to do anything more than an assignment:

int i = 5;
double d = i;

These are also called "widening conversions" and .NET allows you to
perform them without any cast operator because you could never lose any
information doing it: the possible range of valid values of a double
encompasses the range of valid values for an int and then some, so
you're never going to do this assignment and then discover to your
horror that the runtime dropped a few digits off your int value. For
reference types, the rule behind an implicit cast is that the cast
could never throw an InvalidCastException: it is clear to the compiler
that the cast is always valid.

You can make new implicit cast operators for your own types (which
means that you can make implicit casts that break all of the rules, if
you're stupid about it). The basic rule of thumb is that an implicit
cast can never include the possibility of losing information in the
transition.

Note that the underlying representation _did_ change in this
conversion: a double is represented completely differently from an int.

The second kind of conversion is an explicit cast. An explicit cast is
required wherever there is the possibility of losing information, or
there is a possibility that the cast might not be valid and thus throw
an InvalidCastException:

double d = 1.5;
int i = (int)d;

Here you are obviously going to lose information: i will be 1 after the
cast, so the 0.5 gets lost. This is also known as a "narrowing"
conversion, and the compiler requires that you include an explicit cast
(int) to indicate that yes, you know that information may be lost, but
you don't care.

Similarly, with reference types the compiler requires explicit casts in
situations in which the cast may not be valid at run time, as a signal
that yes, you know there's a risk, but you know what you're doing.

The third kind of conversion is one that involves such a radical change
in representation that the designers didn't provide even an explicit
cast: they make you call a method in order to do the conversion:

string s = "15";
int i = Convert.ToInt32(s);

Note that there is nothing that absolutely requires a method call here.
Implicit and explicit casts are method calls too (that's how you make
your own). The designers could quite easily have created an explicit
cast operator that converted a string to an int. The requirement that
you call a method is a stylistic choice rather than a fundamental
requirement of the language.

The stylistic reasoning goes something like this: String-to-int is a
complicated conversion with lots of opportunity for things going
horribly wrong:

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

As such, the method call gives you documentation to read, and a broad
hint that this is something more than just a quick cast.

When designing your own types (particularly your own value types), you
may decide to create cast operators and conversion functions. The lines
dividing "implicit cast", "explicit cast", and "conversion function"
territory are a bit blurry, so different people may make different
decisions as to what should be what. Just try to keep in mind
information loss, and potential for exceptions and invalid data, and
that should help you decide.
 
Bruce said:
Not true. The truth is a bit more complex than that. .NET provides
three methods of getting from point A to point B, as it were.

When I was talking of casting I was of course only talking about casting
in terms of objects and not of primitive types.
Note that the underlying representation _did_ change in this
conversion: a double is represented completely differently from an int.

Well, because it was a conversion and not a cast.
Note that there is nothing that absolutely requires a method call here.
The designers could quite easily have created an explicit
cast operator that converted a string to an int. The requirement that
you call a method is a stylistic choice rather than a fundamental
requirement of the language.

As proven by PHP.
Implicit and explicit casts are method calls too (that's how you make
your own).

I have to say I am not extremely well familiar with C# internals but I
doubt it calls a method for a simple cast. Casting an instance from
object to string will probably only tell the compiler not to report the
typical incompatible types message - along with additional checks for
possible unsupported casting exceptions.
 
I have to say I am not extremely well familiar with C# internals but I
doubt it calls a method for a simple cast. Casting an instance from
object to string will probably only tell the compiler not to report the
typical incompatible types message - along with additional checks for
possible unsupported casting exceptions.

Hmmm... I'm not sure about the C# compiler, and even less sure about
the JIT compiler (remember the C# 'compiler' actually translates source
code into MSIL !), but if you had to design the compiler, wouldn't you
simply make it instantiate an 'anonymous' instance of the class that
the object needs to be converted to and use that instance from that
point on (till end of scope, evidently) ?

I got a feeling it might be more complicated to tell the compiler not
to report errors than to make an instance of the casted-to class and
use that (this second alternative sounds safer to me too, on top of
that).

F.O.R.
 
Olorin said:
Hmmm... I'm not sure about the C# compiler, and even less sure about
the JIT compiler (remember the C# 'compiler' actually translates source
code into MSIL !), but if you had to design the compiler, wouldn't you
simply make it instantiate an 'anonymous' instance of the class that
the object needs to be converted to and use that instance from that
point on (till end of scope, evidently) ?

I got a feeling it might be more complicated to tell the compiler not
to report errors than to make an instance of the casted-to class and
use that (this second alternative sounds safer to me too, on top of
that).

F.O.R.

This might be very well possible, as I said I do not really know how it
is internally handled.

The only thing I would wonder about, would be that by instantiating a
second instance with absolutely the indentical instance data (not only
member values but also all instance states like locks, ....) it might
cause some confusion. I'd see it as easier to simply perform a check
whether the assigned class is compatible with the cast and do it if
everything is okay.
 
Not true. The truth is a bit more complex than that. .NET provides
When I was talking of casting I was of course only talking about casting
in terms of objects and not of primitive types.

Sorry. I misunderstood, as the OP was giving examples of primitive type
casts. My reply was more directed at the OP than at your post.
I have to say I am not extremely well familiar with C# internals but I
doubt it calls a method for a simple cast. Casting an instance from
object to string will probably only tell the compiler not to report the
typical incompatible types message - along with additional checks for
possible unsupported casting exceptions.

What you say is true for casts up and down the reference type
hierarchy, but not for other kinds of "casts" (which are really
conversions, as you pointed out, but which use the cast notation and
therefore are rightly referred to as "casts").

Casting a reference type to one of its parent types (up the class
hierarchy) or to a child type (down the class hierarchy) does not
involve anonymous instances or any copying at all. It simply, as you
mentioned, copies the reference to a variable of another type. Both
variables continue to point at the same object instance, and will
usually interpret all method calls and property references the same
(unless a method or property is declared "new").

When I was talking about casting to a string (or from a string), I was
not referring to a simple cast down the inheritance hierarchy like
this:

Object o = "abcdef";
string s = (string)o;

which in fact does nothing more than copy the reference to "abcdef"
from o to s, along with the necessary run-time type compatibility
checking. I was, instead, referring to a cast like this:

MyClass mc = new MyClass();
string s = (string)mc;

which in C# is possible if you declare an explicit or implicit cast
operator that casts from MyClass to a string. That "cast" is, in fact,
a call to the static method you declare that performs the conversion.
(If the cast operator is implicit then you can express the second line
like this:

string s = mc;

with no complaint from the compiler. Only explicit casts _require_ the
(string) cast notation.)

Of course, when dealing with built-in primitive types and casts up and
down the class hierarchy the compiler doesn't bother calling a method.
A method call is required only for casts that you define yourself.
 
Back
Top