views:

1816

answers:

12

Eric Lippert's comments in this question have left me thoroughly confused. What is the difference between casting and conversion in C#?

+6  A: 

Just my understanding, probably much too simple:

When casting the essential data remains intact (same internal representation) - "I know this is a dictionary, but you can use it as a ICollection".

When converting, you are changing the internal representation to something else - "I want this int to be a string".

Oded
A cast from a short to an int in C# also causes a conversion (2 bytes to 4 bytes). Only casts up or down an reference-type object heirarachy do not cause conversions.
Jeffrey L Whitledge
What you describe as a casting is actually a widening conversion. http://msdn.microsoft.com/en-us/library/k1e94s7e%28VS.80%29.aspx
Guffa
@Jeffrey L Whitledge, @Guffa - thanks for the correction. Answer updated.
Oded
+32  A: 

Casting is a way of telling the compiler "Object X is really Type Y, go ahead and treat it as such."

Conversion is saying "I know Object X isn't Type Y, but there exists a way of creating a new Object from X of Type Y, go ahead and do it."

chrissr
Great definition, but why then (int)5.5 is called a cast in C/C++ ? It is definitely a conversion.
Andrey
I love easy logical explainations like these. +1
Mike
Also what do you think about typical C# compilation error:"Cannot implicitly convert type 'object' to 'string'. An explicit conversion exists (are you missing a cast?)" looks like everything gets mixed.
Andrey
I would guess that the term "cast" has a bit of a muddy definition and usage. Casting primitives involves explicit conversion. It's only reference types where casting behaves as chrissr explained. Just doing this: `double a = 4.5; int b = a;` yields an accurate error message alluding to this: `Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)` ----- that's all in C#, I suspect C and C++ are the same story though.
Matt Greer
I don't believe that this reflects the spirit of what Eric was trying to say. From my reading, he was not describing the behavior as "either `cast` or `convert`, but rather the *cast* being what's present in the code (in other words, the *cast operator*), where as *conversion* being what actually takes place. Very few conversions result in an identical in-memory representation (an example being casting between signed and unsigned versions of the same type, like `int` and `uint`, or casts to base types and interfaces).
Adam Robinson
Your answer is actually incorrect according to the MSDN documentation: `x = (int)y` where `y` is a `double` *is a cast*. (See the link in my answer.)
Dan Puzey
@Dan Puzey it is partially incorrect. his answer is valid for interfaces/base classes.
Andrey
@Matt I agree on the muddyness. The error message itself even says a conversion exists, but then suggests you use a cast to perform the conversion. `An explicit conversion exists (are you missing a cast?)`
AaronLS
@Andrey: you don't need an explicit conversion for that scenario - you can use implicit conversion (that is, if I have `List<int> myList` and then write `IEnumerable x = myList`, this is a valid *conversion* - I don't need to perform a cast with `IEnumerable x = (IEnumerable)myList`.
Dan Puzey
@Dan Puzey sorry, i meant `(string)someObject`
Andrey
@Andrey: ah, fair point - hadn't spotted that one.
Dan Puzey
@Matt Greer: Converting primitives does not always involve use of the cast operator. For example I can write `int a = 4; long b = a;` with no problem because there is an implicit conversion from `int` to `long`.
Jason Punyon
@Jason -- but you are still going against chrissr's answer. You have done a conversion (only this time it is implicit). The bottom line is casting just means different things for value types and reference types and requires some context to truly understand what it means to "cast".
Matt Greer
@Jason and @Matt: I'm not sure it's different for value vs. refence types - the difference in Jason's example is that the conversion is (by definition) lossless and can be done implicitly (as with, say, `string` to `object` assignment). A potentially lossy or failable conversion (like `long` to `int` or `object` to `string`) requires a cast operator.
Dan Puzey
I would say that the distinction you are drawing is not casting vs conversion, but rather that of representation preserving conversions vs representation changing conversions. On the JScript team we made that distinction by calling the former "conversions" and the latter "coercions", but the distinction was pretty subtle.
Eric Lippert
+19  A: 

I believe what Eric is trying to say is:

Casting is a term describing syntax (hence the Syntactic meaning).

Conversion is a term describing what actions are actually taken behind the scenes (and thus the Semantic meaning).

A cast-expression is used to convert explicitly an expression to a given type.

And

A cast-expression of the form (T)E, where T is a type and E is a unary-expression, performs an explicit conversion (§13.2) of the value of E to type T.

Seems to back that up by saying that a cast operator in the syntax performs an explicit conversion.

Justin Niessner
+1. So far the only answer I've seen that seems to pair up with what Eric was saying.
Adam Robinson
+1: Succinct. (15 chars)
MikeD
No, I don't think that's what he meant. The syntax is called casting, but it doesn't always do a conversion behind the scenes. If you actually do a casting, there is no conversion going on. It might not even create any code at all, but only tell the compiler what type it should consider a reference to be.
Guffa
In the context of the C# language, cast does mean this. In the context of IL, the `castclass` opcode has the meaning that others have described (interpret the reference as a different type.) So the 'cast operator' may resolve to either a cast or a conversion in the emitted IL.
Dan Bryant
@Guffa: So what you are saying is that an "identity conversion" -- a conversion from, say, int to int -- is not a conversion? An interesting position but one not supported by the C# specification.
Eric Lippert
Some conversions are just reinterpretations, some are not and require actual code behind the scenes to perform. Some conversions are done implicitly, others require an explicit cast. There's *no* correlation between the two statements above; some implicit conversions cause code to be generated, some explicit casts do not. However, (I believe that) all cases where the generated conversion can throw an exception require an explicit cast.
Donal Fellows
@Donal: To be precise, the guidelines state that any conversion that could fail at runtime *or lose information* should require an explicit conversion. There isn't anything, however, that actually prevents an implicit conversion from throwing an exception.
Adam Robinson
@Adam: though ideally implicit conversions do not lose information, some of the built-in implicit conversions do so. For example, when going between 64 bit integer and 64 bit float, bits of precision can be lost. The conversion does not lose *magnitude*, but it does lose *information*.
Eric Lippert
@Eric: I hadn't thought of that scenario. While I can understand the desire not to make those explicit (since, conceptually but not practically, it's a widening conversion), doesn't that violate the "letter of the law", so to speak?
Adam Robinson
@Adam: Yes, it is a bit of a violation to lose information in this manner. However, I think it's a reasonable exception to the general rule. If you are the sort of person who does math in doubles then you are already the sort of person willing to take on rounding errors.
Eric Lippert
@Eric: Yeah, I think it's reasonable too, especially given (as you point out) the approximated nature of floating point numbers anyway.
Adam Robinson
+1  A: 

In this context, casting means that you are exposing an object of a given type for manipulation as some other type, conversion means that you are actually changing an object of a given type to an object of another type.

kekekela
A: 

This page of the MSDN C# documentation suggests that a cast is specific instance of conversion: the "explicit conversion." That is, a conversion of the form x = (int)y is a cast.

Automatic data type changes (such as myLong = myInt) are the more generic "conversion."

Dan Puzey
No, it doesn't suggest that a cast is a type of conversion, it says that in order to perform an explicit conversion, a cast (specifically, the use of the *cast operator*) is required. Casting is a *language instruction*, not *an operation* that's distinct from conversion.
Adam Robinson
True; the page suggests that the casting operator is required for explicit conversion, and that this is required if any data might be lost in the conversion. So yes, technically casting is the operation that *performs* a type of coversion, but I think my answer is still closer to the truth than the current top-voted one (which contradicts the documentation entirely). Jason Punyon's answer gets my vote!
Dan Puzey
+2  A: 

After reading Eric's comments, an attempt in plain english:

Casting means that the two types are actually the same at some level. They may implement the same interface or inherit from the same base class or the target can be "same enough" (a superset?) for the cast to work such as casting from Int16 to Int32.

Converting types then means that the two objects may be similar enough to be converted. Take for example a string representation of a number. It is a string, it cannot simply be cast into a number, it needs to be parsed and converted from one to the other, and, the process may fail. It may fail for casting as well but I imagine that's a much less expensive failure.

And that's the key difference between the two concepts I think. Conversion will entail some sort of parsing, or deeper analysis and conversion of the source data. Casting does not parse. It simply attempts a match at some polymorphic level.

Paul Sasik
+5  A: 

From the C# Spec 14.6.6:

A cast-expression is used to convert explicitly an expression to a given type.
...
A cast-expression of the form (T)E, where T is a type and E is a unary-expression, performs an explicit conversion (§13.2) of the value of E to type T.

So casting is a syntactic construct used to instruct the compiler to invoke explicit conversions.

From the C# Spec §13:

A conversion enables an expression of one type to be treated as another type. Conversions can be implicit or explicit, and this determines whether an explicit cast is required. [Example: For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. The opposite conversion, from type long to type int, is explicit, so an explicit cast is required.

So conversions are where the actual work gets done. You'll note that the cast-expression quote says that it performs explicit conversions but explicit conversions are a superset of implicit conversions, so you can also invoke implicit conversions (even if you don't have to) via cast-expressions.

Jason Punyon
...among other things. The casting syntax can also be used to instruct the compiler to do a casting.
Guffa
@Guffa: Do you have a reference for that? There are only 5 instances of the word "casting" in the body of the C# spec and none of those instances define anything...
Jason Punyon
+1  A: 

Casting is the creation of a value of one type from another value of another type. Conversion is a type of casting in which the internal representation of the value must also be changed (rather than just its interpretation).

In C#, casting and converting are both done with a cast-expression:

( type ) unary-expression

The distinction is important (and the point is made in the comment) because only conversions may be created by a conversion-operator-declarator. Therefore, only (implicit or explicit) conversions may be created in code.

A non-conversion implicit cast is always available for subtype-to-supertype casts, and a non-conversion explicit cast is always available for supertype-to-subtype casts. No other non-conversion casts are allowed.

Jeffrey L Whitledge
A: 

A cast is an operator on a class/struct. A conversion is a method/process on one or the other of the affected classes/structs, or may be in a complete different class/struct (i.e. Converter.ToInt32()

Cast operators come in two flavors: implicit and explicit

Implicit cast operators indicate that data of one type (say, Int32) can always be represented as another type (decimal) without loss of data/precision.

int i = 25;
decimal d = i;

Explicit cast operators indicate that data of one type (decimal) can always be faithfully represented as another type (int), but there may be loss of data/precision. Therefor the compiler requires you to explicitly state that you are aware of this and want to do it anyway, through use of the explicit cast syntax:

decimal d = 25.0001;
int i = (int)d;

Conversion takes two types that are not necessarily related in any way, and attempts to convert one into the other through some process, such as parsing. If all known conversion algorithms fail, the process may either throw an exception or return a default value:

string s = "200";
int i = Converter.ToInt32(s); // set i to 200 by parsing s

string s = "two hundred";
int i = Converter.ToInt32(s); // sets i to 0 because the parse fails

Eric's references to syntactic conversion vs. symantic conversion are basically an operator vs. methodology distinction.

Toby
A: 

A cast is syntactical, and may or may not involve a conversion (depending on the type of cast). As you know, C++ allows specifying the type of cast you want to use.

Casting up/down the hierarchy may or may not be considered conversion, depending on who you ask (and what language they're talking about!)

Eric (C#) is saying that casting to a different type always involves a conversion, though that conversion may not even change the internal representation of the instance.

A C++-guy will disagree, since a static_cast might not result in any extra code (so the "conversion" is not actually real!)

BlueRaja - Danny Pflughoeft
A: 

Casting and Conversion are basically the same concept in C#, except that a conversion may be done using any method such as Object.ToString(). Casting is only done with the casting operator (T) E, that is described in other posts, and may make use of conversions or boxing.

Which conversion method does it use? The compiler decides based on the classes and libraries provided to the compiler at compile-time. If an implicit conversion exists, you are not required to use the casting operator. Object o = String.Empty. If only explicit conversions exist, you must use the casting operator. String s = (String) o.

You can create explicit and implicit conversion operators in your own classes. Note: conversions can make the data look very similar or nothing like the original type to you and me, but it's all defined by the conversion methods, and makes it legal to the compiler.

Casting always refers to the use of the casting operator. You can write

Object o = float.NaN;
String s = (String) o;

But if you access s, in for example a Console.WriteLine, you will receive a runtime InvalidCastException. So, the cast operator still attempts to use conversion at access time, but will settle for boxing during assignment.

maxwellb
+20  A: 

I am reminded of the anecdote told by Richard Feynman where he is attending a philosophy class and the professor askes him "Feynman, you're a physicist, in your opinion is an electron an 'essential object'?" So Feynman asks the clarifying question "is a brick an essential object?" to the class. Every student has a different answer to that question. They say that the fundamental abstract notion of "brickness" is the essential object. No, one specific, unique brick is the essential object. No, the parts of the brick you can empirically observe is the essential object. And so on.

Which is of course not to answer your question.

I'm not going to go through all these dozen answers and debate with their authors about what I really meant. I'll write a blog article on the subject in a few weeks and we'll see if that throws any light on the matter.

How about an analogy though, a la Feynman. You wish to bake a loaf of banana bread Saturday morning (as I do almost every Saturday morning.) So you consult The Joy of Cooking, and it says "blah blah blah... In another bowl, whisk together the dry ingredients. ..."

Clearly there is a strong relationship between that instruction and your actions tomorrow morning, but equally clearly it would be a mistake to conflate the instruction with the action. The instruction consists of text. It has a location, on a particular page. It has punctuation. Were you to be in the kitchen whisking together flour and baking soda, and someone asked "what's your punctuation right now?", you'd probably think it was an odd question. The action is related to the instruction, but the textual properties of the instruction are not properties of the action.

A cast is not a conversion in the same way that a recipe is not the act of baking a cake. A recipe is text which describes an action, which you can then perform. A cast operator is text which describes an action - a conversion - which the runtime can then perform.

Eric Lippert
No doubt if C# is in strong hands.
this. __curious_geek
Part of me wonders what it is like to work with Eric. The other part hopes I didn't butcher his meaning too much in my post.
Justin Niessner