Quelle est la différence entre casting et conversion? [dupliquer]

cette question a déjà une réponse ici:

les commentaires d'Eric Lippert dans cette question m'ont laissé complètement confus. Quelle est la différence entre la coulée et la conversion en C#?

66
demandé sur Community 2010-07-02 18:59:01

13 réponses

je crois que ce Qu'Eric essaie de dire est:

Casting est un terme qui décrit la syntaxe (d'où le sens syntaxique ).

Conversion est un terme qui décrit les actions réellement entreprises en coulisse (et donc le sémantique sens).

une expression en fonte est utilisée pour convertir explicitement une expression d'une donnée type.

et

expression coulée de la forme (T)E, où T est un type et E est un une expression simple, effectue une conversion (§13.2) de la valeur de E à la catégorie T.

semble confirmer cela en disant qu'un opérateur de distribution dans la syntaxe effectue une conversion explicite.

44
répondu Justin Niessner 2010-07-02 15:18:40

Casting est une façon de dire au compilateur "L'objet X est vraiment de Type Y, allez-y et traitez-le comme tel."

la Conversion dit "je sais que L'objet X n'est pas de Type Y, mais il existe un moyen de créer un nouvel objet à partir de X de Type Y, allez-y et faites-le."

77
répondu chrissr 2010-07-02 15:07:04

je me souviens de L'anecdote racontée par Richard Feynman où il assiste à un cours de philosophie et le professeur lui demande" Feynman, vous êtes un physicien, à votre avis Un électron est un "objet essentiel"?"Feynman pose donc la question de clarification" une brique est-elle un objet essentiel?"à la classe. Chaque élève a une réponse différente à cette question. Ils disent que la notion abstraite fondamentale de "brique" est l'objet essentiel. Non, une brique spécifique et unique est la objet essentiel. Non, les parties de la brique que vous pouvez observer empiriquement sont l'objet essentiel. Et ainsi de suite.

ce qui est bien sûr de ne pas répondre à votre question.

Je ne vais pas passer par toutes ces douzaines de réponses et de débats avec leurs auteurs sur ce que je voulais vraiment dire. Je vais écrire un article de blog sur le sujet dans quelques semaines et nous allons voir si cela jette une lumière sur la question.

Que Diriez-vous d'une analogie cependant, une la Feynman. Vous souhaitez faire cuire un pain de banane le samedi matin (comme je le fais presque tous les samedis matin. Donc, vous consultez la joie de cuisiner, et il est dit " bla bla bla... Dans un autre bol, fouetter les ingrédients secs. ..."

il est clair qu'il y a une forte relation entre cette instruction et vos actions demain matin, mais il est tout aussi clair que ce serait une erreur de confondre instruction avec action . L'instruction se compose de texte. Il a un emplacement, sur une page particulière. Il a des signes de ponctuation. Étiez-vous dans la cuisine à fouetter ensemble la farine et le bicarbonate de soude, et quelqu'un a demandé "Quelle est votre ponctuation en ce moment?", vous penseriez probablement que c'était une question étrange. L'action est liée à l'instruction, mais le texte propriétés de l'instruction ne sont pas des propriétés de l'action.

Un plâtre n'est pas une conversion de la même manière qu'une recette n'est pas la loi de la cuisson d'un gâteau. Une recette est un texte qui décrit une action, que vous pouvez ensuite effectuer. Un opérateur cast est un texte qui décrit une action - une conversion - que l'exécution peut alors effectuer.

42
répondu Eric Lippert 2010-07-02 16:49:53

du C# Spec 14.6.6:

une expression en fonte est utilisée pour convertir explicitement une expression donnée type.

...

Fonte expression de la forme (T)E, où T est un type et E est un une expression simple, effectue une conversion (§13.2) de la valeur de E à la catégorie T.

donc la coulée est une construction syntaxique utilisée pour donner l'instruction au compilateur de invoquez les conversions explicites.

du C# Spec §13:

une conversion permet une expression de un type à traiter comme un autre type. Les Conversions peuvent être implicites ou explicite, et cela détermine si une distribution explicite est requise. [Exemple: Par exemple, la conversion du type int au type long est implicite, de sorte que les expressions de type int peut implicitement être traité comme type long. La conversion opposée, de type longue de type int, est explicite, donc une distribution explicite est requise.

donc les conversions sont là où le travail réel est fait. Vous noterez que la citation de cast-expression dit qu'il effectue des conversions explicites, mais les conversions explicites sont un super-ensemble de conversions implicites, de sorte que vous pouvez également invoquer des conversions implicites (même si vous n'avez pas à le faire) via cast-expressions.

7
répondu Jason Punyon 2010-07-02 17:52:06

Juste ma compréhension, sans doute beaucoup trop simple:

lors du moulage des données essentielles reste intact (même représentation interne) - "je sais que c'est un dictionnaire, mais vous pouvez l'utiliser comme une ICollection".

lors de la conversion, vous changez la représentation interne en quelque chose d'autre - "je veux que cet int soit une chaîne".

6
répondu Oded 2010-07-02 15:37:10

après avoir lu les commentaires D'Eric, une tentative en anglais simple:

moulage signifie que les deux types sont en fait les mêmes à un certain niveau. Ils peuvent implémenter la même interface ou hériter de la même classe de base ou la cible peut être "assez identique" (un super-ensemble?) pour que la fonte fonctionne comme la fonte de Int16 à Int32.

conversion signifie Alors que les deux objets peuvent être similaires assez pour être converti. Prenez par exemple une chaîne représentant un nombre. C'est une chaîne, elle ne peut pas être simplement coulée dans un nombre, elle doit être analysée et convertie de l'une à l'autre, et, le processus peut échouer. Il peut échouer pour le casting aussi bien, mais j'imagine que c'est un échec beaucoup moins cher.

et c'est la différence clé entre les deux concepts je pense. La Conversion impliquera une sorte d'analyse, ou une analyse plus approfondie et la conversion des données source. Le Casting ne se discute pas. Il tente simplement une correspondance à un certain niveau polymorphe.

5
répondu Paul Sasik 2010-07-02 15:21:21

Casting est la création d'une valeur d'un type à partir d'une autre valeur d'un autre type. Conversion est un type de moulage dans lequel la représentation interne de la valeur doit également être changée (plutôt que seulement son interprétation).

En C#, le moulage et la conversion sont à la fois fait avec un la fonte de l'expression :

( type ) unaire-l'expression

la distinction est importante (et ce point est souligné dans le commentaire) parce que seules les conversions peuvent être créées par un conversion-operator-declarator . Par conséquent, seules les conversions (implicites ou explicites) peuvent être créées en code.

un moulage implicite de non-conversion est toujours disponible pour les moulages de sous-type à supertype, et un moulage explicite de non-conversion est toujours disponible pour les moulages de supertype à sous-type jeter. Aucun autre moulage sans conversion n'est autorisé.

2
répondu Jeffrey L Whitledge 2010-07-02 15:24:25

dans ce contexte, casting signifie que vous exposez un objet d'un type donné à des fins de manipulation comme un autre type, conversion signifie que vous changez effectivement un objet d'un type donné en un objet d'un autre type.

1
répondu heisenberg 2010-07-02 15:08:35

Cette page de la MSDN C# documentation suggère que la fonte est l'instance spécifique de conversion: la "conversion explicite."C'est une conversion de la forme x = (int)y est une fonte.

Les changements automatiques de type de données

(tels que myLong = myInt ) sont la conversion plus générique."

0
répondu Dan Puzey 2010-07-02 15:10:13

Une fonte est un opérateur sur un class/struct. Une conversion est une méthode / procédé sur l'une ou l'autre des classes/structures concernées, ou peut être dans une classe/structure complètement différente (i.e. Converter.ToInt32()

les opérateurs Cast viennent en deux saveurs: implicite et explicite

les opérateurs de coulée implicites indiquent que les données d'un type (disons, Int32) peuvent toujours être représentées comme un autre type (décimal) sans perte de données / précision .

int i = 25;
decimal d = i;

les opérateurs de coulée explicites indiquent que les données d'un type (décimal) peuvent toujours être fidèlement représentées comme un autre type (int), mais il peut y avoir perte de données/précision. Par conséquent, le compilateur vous demande de explicitement déclarer que vous êtes au courant de cela et que vous voulez le faire de toute façon, en utilisant la syntaxe explicite cast:

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

Conversion prend deux types qui ne sont pas nécessairement liés d'une façon ou d'une autre, et tente de convertir l'un en l'autre par un processus quelconque, tel que l'analyse. Si tous les algorithmes de conversion connus échouent, le processus peut soit jeter une exception ou retourner une valeur par défaut:

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

les références D'Eric à la conversion syntaxique par rapport à la conversion sémantique sont essentiellement une distinction opérateur par rapport à la méthodologie.

0
répondu Toby 2010-07-02 15:31:39

une coulée est syntaxique, et peut impliquer ou non une conversion (selon le type de coulée). Comme vous le savez, C++ permet de spécifier le type de distribution que vous voulez utiliser.

élever/descendre la hiérarchie peut ou non être considéré comme une conversion, selon qui vous demandez (et de quelle langue ils parlent!)

Eric (C#) dit que le casting à un type différent implique toujours un conversion, bien que cette conversion ne puisse même pas changer la représentation interne de l'instance.

C++-guy ne seront pas d'accord, depuis un static_cast n'aboutissent pas à de code supplémentaire (donc la "conversion" n'est pas vraiment réel!)

0
répondu BlueRaja - Danny Pflughoeft 2017-05-23 10:30:00

Coulée et de Conversion sont fondamentalement le même concept en C#, à l'exception de la conversion peut être fait en utilisant une méthode comme Object.ToString() . Le Casting se fait uniquement avec l'opérateur de casting (T) E , qui est décrit dans d'autres Billets, et peut utiliser des conversions ou de la boxe.

Quelle méthode de conversion utilise-t-elle? Le compilateur décide en fonction des classes et des bibliothèques fournies au compilateur au moment de la compilation. Si une conversion implicite existe, vous êtes pas besoin d'utiliser l'opérateur de coulée. Object o = String.Empty . S'il n'existe que des conversions explicites, vous devez utiliser l'opérateur de coulée. String s = (String) o .

vous pouvez créer explicit et implicit conversion opérateurs dans vos propres classes. Note: les conversions peuvent rendre les données très similaires ou rien comme le type d'origine pour vous et moi, mais tout est défini par les méthodes de conversion, et le rend légal pour le compilateur.

Casting toujours se réfère à l'utilisation de l'opérateur de coulée. Vous pouvez écrire

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

Mais si vous accédez à s , par exemple dans un Console.WriteLine , vous recevrez un runtime InvalidCastException . Ainsi, l'opérateur de cast tente toujours d'utiliser la conversion au moment de l'accès, mais se contentera de boxe pendant la mission.

0
répondu maxwellb 2010-07-02 16:06:13

a inséré EDIT#2: n'est-ce pas hilarant myopia inconsistant que depuis que j'ai fourni cette réponse, la question a été marquée comme une copie d'une question qui demande, " est la même chose que la conversion? ". Et les réponses de" non "sont massivement rétrogradées . Pourtant, ma réponse ici qui souligne l'essence générative pour pourquoi les moulages ne sont pas la même que la conversion est massivement rétrograde ( pourtant, je n'ai pas 1 + 1 dans les commentaires ). Je suppose que les lecteurs ont de la difficulté à comprendre que les casts s'appliquent à la couche Syntaxe/sémantique dénotationnelle et que les conversions s'appliquent à la couche sémantique opérationnelle. Par exemple, un cast d'une référence (ou pointeur en C/C++)-se référant à un type de données en encadré-à un autre type de données, ne génère pas (dans tous les langages et scénarios) une conversion des données en encadré. Par exemple, dans C float a[1]; int* p = (int*)&a; ne garantit pas que *p renvoie aux données int .

un compilateur compile de dénotationnel sémantique" à sémantique opérationnelle . La compilation n'est pas bijective, c'est-à-dire qu'elle n'est pas garantie à uncompile (par exemple Java, LLVM, asm.js, ou C# bytecode) retour à n'importe quelle syntaxe dénotationnelle qui se compile à ce bytecode (par exemple Scala, Python, C#, C via Emscripten, etc). Ainsi les deux couches ne sont pas les mêmes.

donc très clairement un ' cast " et " conversion " ne sont pas la même chose. Ma réponse ici est que les Termes s'appliquent à deux couches différentes de sémantique. Les Casts s'appliquent à la sémantique de ce que la couche dénotationnelle (syntaxe d'entrée du compilateur) connaît. Les Conversions s'appliquent à la sémantique de ce que la couche operational (runtime ou intermediate bytecode) connaît. J'ai utilisé le terme standard de "effacé" pour décrire ce qui arrive à dénotationnel sémantique qui n'est pas explicitement enregistrée dans la couche sémantique opérationnelle.

par exemple, reified generics sont un exemple d'enregistrement de la sémantique dénotationnelle dans la couche sémantique opérationnelle, mais ils ont l'inconvénient de rendre la couche sémantique opérationnelle incompatible avec la sémantique dénotationnelle d'ordre supérieur, par exemple, c'est pourquoi il était douloureux d'envisager la mise en œuvre des génériques de plus grande qualité de Scala sur le CLR de C#parce que la sémantique dénotationnelle de C#pour les génériques étaient codés de façon rigide à la couche sémantique opérationnelle.

arrêtez de rabaisser quelqu'un qui en sait plus que vous. Faire vos devoirs avant de voter.


INSÉRÉE EDIT: le Casting est une opération qui se fait à denotational sémantique de la couche (où les types sont exprimés dans leur intégralité, de la sémantique). Un casting peut (par exemple, conversion explicite) ou non (par exemple, upcasting) provoquer une conversion à l'exécution couche sémantique. Les commentaires négatifs sur ma réponse (et les commentaires positifs sur le commentaire de Marc Gavin) m'indiquent que la plupart des gens ne comprennent pas les différences entre la sémantique dénotationnelle et la sémantique opérationnelle (exécution) . Soupir.


je vais Énoncer la réponse D'Eric Lippert plus simplement et plus généralement pour toutes les langues, y compris C# .

Un cast est syntaxique donc (comme toute syntaxe) est effacé au moment de la compilation ; alors qu'une conversion provoque une action au moment de l'exécution .


C'est une vraie déclaration pour chaque langage informatique que je connais dans l'univers entier. Notez que l'énoncé ci-dessus ne dit pas que moulage et conversions sont mutuellement exclusives.

Un cast peut provoquer un conversion au moment de l'exécution, mais il y a des cas où il ne peut pas.

la raison pour laquelle nous avons deux mots distincts, i.e. cast et conversion , est-ce que nous avons besoin d'un moyen de décrire séparément ce qui se passe dans syntaxe (l'opérateur cast) et à runtime (conversion, ou vérification de type et conversion possible).

il est important que nous maintenions cette séparation des concepts, car dans certains langages de programmation la distribution ne provoque jamais une conversion. De plus, pour que nous comprenions que le casting implicite (par exemple upcasting ) ne se produit qu'au moment de la compilation. La raison pour laquelle j'ai écrit cette réponse est que je veux aider les lecteurs à comprendre en termes d'être multilingue avec les langues informatiques. Et aussi pour voir comment définition générale s'applique correctement dans le C#.

je voulais aussi aider les lecteurs à voir comment je généralise des concepts dans mon esprit, ce qui m'aide en tant que concepteur de langage informatique. J'essaie de transmettre le don d'une pensée très réductionniste et abstraite. Mais j'essaie aussi d'expliquer cela d'une manière très pratique. N'hésitez pas à me le faire savoir dans les commentaires si j'ai besoin d'améliorer l'élucidation.


Eric Lippert a écrit:

Un plâtre n'est pas une conversion de la même manière qu'une recette n'est pas la acte de faire un gâteau. Une recette est un texte qui décrit une action, vous pouvez ensuite effectuer. Un opérateur cast est un texte qui décrit un action - une conversion-que l'exécution peut alors effectuer.

la recette est ce qui se passe en syntaxe. La syntaxe est toujours effacée, et remplacée par rien ou un peu de runtime code.

par exemple, je peux écrire un plâtre en C# qui ne fait rien et est entièrement effacé au moment de la compilation quand il est ne cause pas de changement dans les exigences de stockage ou est upcasting . Nous pouvons clairement voir qu'un cast est juste une syntaxe, qui ne fait aucun changement au code d'exécution.

int x = 1;
int y = (int)x;
Giraffe g = new Giraffe();
Animal a = (Animal)g;

Qui peut être utilisé à des fins de documentation (mais bruyant), mais il est essentiel dans les langues qui ont type inférence, où un cast est parfois nécessaire pour dire au compilateur quel type vous voulez qu'il infère.

pour un exemple , dans Scala un None a le type Option[Nothing]Nothing est le type de fond qui est le sub - type de tous les types possibles (pas super - type). Ainsi, parfois, lors de L'utilisation de None, le type doit être moulé à un type spécifique, parce que Scala seulement fait l'inférence de type local , donc ne peut pas toujours inférer le type que vous vouliez.

// (None : Option[Int]) casts None to Option[Int]
println(Some(7) <*> ((None : Option[Int]) <*> (Some(9) > add)))

une distribution peut savoir au moment de la compilation qu'elle nécessite une conversion de type, par exemple int x = (int)1.5 , ou qu'elle peut exiger un contrôle de type et une conversion de type possible à l'exécution, par exemple downcasting . La distribution (c'est-à-dire la syntaxe) est effacée et remplacée par l'action runtime.

Ainsi, nous pouvons clairement voir que assimiler tous les casts à une conversion explicite est une erreur d'implication dans la """"""""" . Cette documentation entend dire que la conversion explicite nécessite un opérateur , mais elle ne devrait pas être en train de sous-entendre que tous les casts sont des conversions explicites. Je suis sûr Qu'Eric Lippert pourra clarifier cela quand il écrira le blog qu'il a promis dans sa réponse.


ajouter : des commentaires et du chat, je peux voir qu'il y a une certaine confusion sur le sens du terme effacé .

le terme "effacé" est utilisé pour décrire des informations qui étaient connues au moment de la compilation et qui ne le sont pas au moment de l'exécution. Par exemple, les types peuvent être effacés dans les génériques non-reified, et il est appelé type erasure .

en général toute la syntaxe est effacée, parce que généralement CLI n'est pas bijectif (inversible, et un-à-un) avec C#. Vous ne pouvez pas toujours revenir en arrière à partir d'un code CLI arbitraire pour revenir au code source C# exact. Cela signifie que l'information a été effacée.

ceux qui disent effacé n'est pas le bon terme, sont en train de confondre la mise en œuvre d'une distribution avec la sémantique de la distribution. La distribution est une sémantique de plus haut niveau (je pense qu'il est en fait plus élevé que syntaxe , il est la sémantique dénotationnelle au moins en cas de upcasting et downcasting) qui dit à ce niveau de sémantique que nous voulons lancer le type. Maintenant, comment cela se fait à l'exécution est tout à fait différent niveau de sémantique. Dans certaines langues, il peut toujours s'agir d'un NOOP . Par exemple, dans Haskell toutes les informations de typage sont effacées au moment de la compilation.

-6
répondu Shelby Moore III 2017-05-23 11:55:13