Différence entre la conversion et l'utilisation de la méthode Convert.To ()


89

J'ai une fonction qui jette un doublesur les stringvaleurs.

string variable = "5.00"; 

double varDouble = (double)variable;

Une modification de code a été archivée et le projet se construit avec l'erreur: System.InvalidCastException: Specified cast is not valid.

Cependant, après avoir fait ce qui suit ...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

... le projet se construit sans aucune erreur.

Quelle est la différence entre le moulage et l'utilisation de la Convert.To()méthode? Pourquoi le casting lance-t-il un Exceptionet l'utilisation du Convert.To()ne le fait pas?

c#  casting 


6
En ce qui concerne une question référencée , l'OP demande quand utiliser un casting ou une conversion, et la réponse acceptée déclare: "C'est vraiment une question de choix, quel que soit celui que vous utilisez." Je demande la différence entre un casting et un converti. À mon avis, les réponses ci-dessous (bravo SO!) Fournissent plus de détails sur les différences par rapport à "utiliser ceci ou cela par choix" ... et ce détail pourrait être utilisé pour faire un choix plus éclairé, en substance.

@ edmastermind29 il n'y a pas beaucoup de différence entre "quelle est la différence entre x et y" et "quand utiliser x et y" dans le contexte de programmation. Les deux se répondent mutuellement.
nawfal

2
Presque 3 ans plus tard, il ne semble pas que l'un réponde mutuellement à l'autre dans ce cas. Q: "Quelle est la différence entre X et Y?" R: "C'est vraiment une question de choix quel que soit celui que vous utilisez." Pas très utile.

Personne ne semble avoir de réponse directe à laquelle Performs best fait également partie de la question, D'après mon expérience, je vois que Cast est meilleur, en particulier pour obtenir des valeurs de colonne comme celle-ci .. (int) datatable.Rows [0] [0], if nous savons que son int 100%
Sundara Prabu

Réponses:


126

Même si vous pouvez les voir d'une manière ou d'une autre comme équivalents, leur objectif est complètement différent. Essayons d'abord de définir ce qu'est un casting:

La diffusion est l'action de changer une entité d'un type de données en un autre.

C'est un peu générique et c'est en quelque sorte équivalent à une conversion car un cast a souvent la même syntaxe d'une conversion, donc la question devrait être quand un cast (implicite ou explicite) est autorisé par le langage et quand faut-il utiliser un ( plus) conversion explicite?

Permettez-moi d'abord de tracer une ligne simple entre eux. Formellement (même si équivalent pour la syntaxe du langage) un casting va changer le type tandis qu'une conversion / peut changer la valeur (éventuellement en même temps avec le type). De plus, un casting est réversible alors qu'une conversion peut ne pas l'être.

Ce sujet est assez vaste, alors essayons de le réduire un peu en excluant les opérateurs de diffusion personnalisés du jeu.

Casts implicites

En C #, un cast est implicite lorsque vous ne perdez aucune information (veuillez noter que cette vérification est effectuée avec les types et non avec leurs valeurs réelles ).

Types primitifs

Par exemple:

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

Ces transtypages sont implicites car lors de la conversion, vous ne perdrez aucune information (vous élargissez simplement le type). À l'inverse, la conversion implicite n'est pas autorisée car, quelles que soient leurs valeurs réelles (car elles ne peuvent être vérifiées qu'au moment de l'exécution), pendant la conversion, vous risquez de perdre certaines informations. Par exemple, ce code ne se compilera pas car a doublepeut contenir (et en fait il le fait) une valeur non représentable avec a float:

// won't compile!
double bigReal = Double.MaxValue;
float tinyReal = bigReal;

Objets

Dans le cas d'un objet (un pointeur vers), le cast est toujours implicite lorsque le compilateur peut être sûr que le type source est une classe dérivée (ou il implémente) le type de la classe cible, par exemple:

string text = "123";
IFormattable formattable = text;

NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;

Dans ce cas, le compilateur sait que stringimplémente IFormattableet qui NotSupportedExceptionest (dérive de) Exceptiondonc le cast est implicite. Aucune information n'est perdue car les objets ne changent pas de type (c'est différent avec structles types s et primitifs car avec une distribution vous créez un nouvel objet d'un autre type ), ce qui change, c'est votre vision d'eux.

Casts explicites

Un cast est explicite lorsque la conversion n'est pas effectuée implicitement par le compilateur et que vous devez ensuite utiliser l'opérateur de cast. Cela signifie généralement que:

  • Vous pouvez perdre des informations ou des données, vous devez donc en être conscient.
  • La conversion peut échouer (car vous ne pouvez pas convertir un type en un autre) donc, encore une fois, vous devez être conscient de ce que vous faites.

Types primitifs

Un cast explicite est requis pour les types primitifs lorsque, lors de la conversion, vous risquez de perdre certaines données, par exemple:

double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;

float epsilon = (float)Double.Epsilon;

Dans les deux exemples, même si les valeurs se situent dans la floatplage, vous perdrez des informations (dans ce cas, la précision), donc la conversion doit être explicite. Maintenant, essayez ceci:

float max = (float)Double.MaxValue;

Cette conversion échouera donc, encore une fois, elle doit être explicite pour que vous en soyez conscient et que vous puissiez faire une vérification (dans l'exemple, la valeur est constante mais elle peut provenir de certains calculs d'exécution ou d'E / S). Revenons à votre exemple:

// won't compile!
string text = "123";
double value = (double)text;

Cela ne compilera pas car le compilateur ne peut pas convertir le texte en nombres. Le texte peut contenir n'importe quel caractère, pas seulement des nombres et c'est trop, en C #, même pour un cast explicite (mais cela peut être autorisé dans une autre langue).

Objets

Les conversions de pointeurs (en objets) peuvent échouer si les types ne sont pas liés, par exemple ce code ne se compilera pas (car le compilateur sait qu'il n'y a pas de conversion possible):

// won't compile!    
string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";

Ce code se compilera mais il peut échouer au moment de l'exécution (cela dépend du type effectif des objets castés) avec un InvalidCastException:

object obj = GetNextObjectFromInput();
string text = (string)obj;

obj = GetNextObjectFromInput();
Exception exception = (Exception)obj;

Les conversions

Donc, enfin, si les casts sont des conversions, pourquoi avons-nous besoin de classes comme Convert? En ignorant les différences subtiles qui proviennent de l' Convertimplémentation et des IConvertibleimplémentations en fait, car en C # avec un cast, vous dites au compilateur:

croyez-moi, ce type est de ce type même si vous ne pouvez pas le savoir maintenant, laissez-moi le faire et vous verrez.

-ou-

ne vous inquiétez pas, je me fiche de savoir si quelque chose sera perdu dans cette conversion.

Pour tout le reste, une opération plus explicite est nécessaire (pensez aux implications des transtypages faciles , c'est pourquoi C ++ a introduit une syntaxe longue, verbeuse et explicite pour eux). Cela peut impliquer une opération complexe (pour string-> la doubleconversion, une analyse sera nécessaire). Une conversion en string, par exemple, est toujours possible (via la ToString()méthode) mais cela peut signifier quelque chose de différent de ce que vous attendez donc cela doit être plus explicite qu'un casting ( plus vous écrivez, plus vous pensez à ce que vous faites ).

Cette conversion peut être effectuée à l'intérieur de l'objet (en utilisant des instructions IL connues pour cela), en utilisant des opérateurs de conversion personnalisés (définis dans la classe à convertir) ou des mécanismes plus complexes ( TypeConverters ou méthodes de classe, par exemple). Vous ne savez pas ce qui va se passer pour faire cela, mais vous savez que cela peut échouer (c'est pourquoi l'OMI, lorsqu'une conversion plus contrôlée est possible, vous devriez l'utiliser). Dans votre cas, la conversion analysera simplement le stringpour produire un double:

double value = Double.Parse(aStringVariable);

Bien sûr, cela peut échouer, donc si vous le faites, vous devriez toujours attraper l'exception qu'il peut lancer ( FormatException). C'est hors sujet ici, mais quand a TryParseest disponible, vous devriez l'utiliser (car sémantiquement vous dites que ce n'est peut-être pas un nombre et que c'est encore plus rapide ... d'échouer).

Les conversions dans .NET peuvent provenir de nombreux endroits, des TypeConverterconversions implicites / explicites avec des opérateurs de conversion définis par l'utilisateur, l'implémentation IConvertibleet des méthodes d'analyse (ai-je oublié quelque chose?). Jetez un œil sur MSDN pour plus de détails à leur sujet.

Pour terminer cette longue réponse, quelques mots sur les opérateurs de conversion définis par l'utilisateur. C'est juste du sucre de laisser le programmeur utiliser une distribution pour convertir un type en un autre. C'est une méthode à l'intérieur d'une classe (celle qui sera castée) qui dit "hé, si il / elle veut convertir ce type en ce type alors je peux le faire". Par exemple:

float? maybe = 10; // Equals to Nullable<float> maybe = 10;
float sure1 = (float)maybe; // With cast
float sure2 = maybe.Value; // Without cast

Dans ce cas, c'est explicite car il peut échouer mais cela est laissé à l'implémentation (même s'il existe des directives à ce sujet). Imaginez que vous écrivez une classe de chaîne personnalisée comme celle-ci:

EasyString text = "123"; // Implicit from string
double value = (string)text; // Explicit to double

Dans votre implémentation, vous pouvez décider de "faciliter la vie du programmeur" et d'exposer cette conversion via un cast (rappelez-vous que c'est juste un raccourci pour écrire moins). Certaines langues peuvent même permettre ceci:

double value = "123";

Autoriser la conversion implicite vers n'importe quel type (la vérification sera effectuée au moment de l'exécution). Avec des options appropriées, cela peut être fait, par exemple, dans VB.NET. C'est juste une philosophie différente.

Que puis-je faire avec eux?

Donc, la dernière question est de savoir quand utiliser l'un ou l'autre. Voyons quand vous pouvez utiliser un cast explicite:

  • Conversions entre les types de base.
  • Conversions de objectvers tout autre type (cela peut également inclure le déballage).
  • Conversions d'une classe dérivée vers une classe de base (ou vers une interface implémentée).
  • Conversions d'un type à un autre via des opérateurs de conversion personnalisés.

Seule la première conversion peut être effectuée avec Convertdonc pour les autres vous n'avez pas le choix et vous devez utiliser une distribution explicite.

Voyons maintenant quand vous pouvez utiliser Convert:

  • Conversions de tout type de base vers un autre type de base (avec certaines limitations, voir MSDN ).
  • Conversions de tout type implémenté IConvertiblevers tout autre type (pris en charge).
  • Conversions depuis / vers un bytetableau vers / depuis une chaîne.

Conclusions

IMO Convertdoit être utilisé chaque fois que vous savez qu'une conversion peut échouer (à cause du format, à cause de la plage ou parce qu'elle peut ne pas être prise en charge), même si la même conversion peut être effectuée avec une conversion (à moins que quelque chose d'autre ne soit disponible). Il indique clairement à qui lira votre code quelle est votre intention et que cela peut échouer (simplification du débogage).

Pour tout le reste, vous devez utiliser un casting, pas de choix, mais si une autre meilleure méthode est disponible, je vous suggère de l'utiliser. Dans votre exemple, une conversion de stringvers doubleest quelque chose qui (surtout si le texte provient de l'utilisateur) échouera très souvent, vous devez donc la rendre aussi explicite que possible (de plus, vous obtenez plus de contrôle sur elle), par exemple en utilisant une TryParseméthode.

Edit: quelle est la différence entre eux?

Selon la question mise à jour et en gardant ce que j'ai écrit auparavant (à propos du moment où vous pouvez utiliser un casting par rapport au moment où vous pouvez / devez utiliser Convert), le dernier point à clarifier est s'il y a une différence entre eux (de plus Convertutilise IConvertibleet IFormattableinterfaces afin qu'il puisse effectuer des opérations non autorisé avec les moulages).

La réponse courte est oui, ils se comportent différemment . Je vois la Convertclasse comme une classe de méthodes d'assistance si souvent qu'elle offre des avantages ou des comportements légèrement différents. Par exemple:

double real = 1.6;
int castedInteger = (int)real; // 1
int convertedInteger = Convert.ToInt32(real); // 2

Assez différent, non? Le cast tronque (c'est ce que nous attendons tous) mais Converteffectue un arrondi à l'entier le plus proche (et cela peut ne pas être attendu si vous n'en êtes pas conscient). Chaque méthode de conversion introduit des différences donc une règle générale ne peut pas être appliquée et elles doivent être vues au cas par cas ... 19 types de base à convertir en tout autre type ... la liste peut être assez longue, mieux vaut consulter le cas MSDN en Cas!


J'ai changé la question à poser, Difference between casting and using the Convert.To() method. Sinon, réponse très complète. (J'espère que ma question est rouverte ...)

@ edmastermind29 J'ai édité un peu la question, le sujet est trop long même pour une longue réponse (plus de 300 conversions possibles à lister). Convert ajoute des avantages (ou simplement des comportements inattendus?) Non seulement par rapport aux casts, mais aussi par rapport aux interfaces IConvertible et IFormattable «simples».
Adriano Repetti

Je n'aime pas la notion empruntée à C selon doublelaquelle les valeurs qui ne représentent pas des nombres entiers devraient être «convertibles» en int. Un casting semble le paradigme approprié dans les cas où l' on est par exemple la récupération des Int32valeurs d'un double[]qui détient un mélange de nombres réels et des Int32valeurs qui ont été converties en double[une tentative de convertir une valeur non représentable précisément en int32indiquerait une condition inattendue et devrait déclencher une exception], mais je pense que quand on veut une conversion avec perte, on devrait être précis sur la forme que l'on veut.
supercat du

1
Une autre différence est entre les types d'objets et les types primitifs. egobject o = 123; var l = Convert.ToInt64(o); var i = (long) (int) o; var f = (long) o // InvalidCastException
yue shi

1
@ rory.ap c'est un point important. Non, formellement ce n'est pas un casting ( float-> int) mais une coercition . Un casting pourrait être par exemple DerivedClass-> BaseClass. C'est déroutant parce qu'en C #, nous utilisons le même mot (et opérateur) pour les deux, mais ce sont en fait des choses distinctes. Une définition formelle pour les distinguer est légèrement plus compliquée que ce que j'ai écrit.
Adriano Repetti le

12

La diffusion est une façon de dire au compilateur: «Je sais que vous pensez que cette variable est une barre, mais j'en sais plus que vous; l'objet est en fait un Foo, alors laissez-moi le traiter comme s'il s'agissait d'un Foo de maintenant. " Ensuite, au moment de l'exécution, si l'objet réel s'est avéré être vraiment un Foo, votre code fonctionne, s'il s'avère que l'objet n'était pas du tout un Foo, vous obtenez une exception. (Plus précisément un System.InvalidCastException.)

La conversion, par contre, est une façon de dire: "Si vous me donnez un objet de type Bar, je peux créer un tout nouvel objet Foo qui représente ce qu'il y a dans cet objet Bar. Je ne changerai pas l'objet d'origine, il gagnera" t traiter l'objet d'origine différemment, il créera quelque chose de nouveau qui est juste basé sur une autre valeur . Quant à la façon dont il le fera, il pourrait être n'importe quoi. Dans ce cas, Convert.ToDoubleil finira par appelerDouble.Parsequi a toutes sortes de logique complexe pour déterminer quels types de chaînes représentent quelles valeurs numériques. Vous pouvez écrire votre propre méthode de conversion qui mappe différemment les chaînes aux doubles (peut-être pour prendre en charge une convention entièrement différente pour l'affichage des nombres, comme les chiffres romains ou autre). Une conversion peut faire n'importe quoi, mais l'idée est que vous ne demandez pas vraiment au compilateur de faire quoi que ce soit pour vous; c'est vous qui écrivez le code pour déterminer comment créer le nouvel objet car le compilateur, sans votre aide, n'a aucun moyen de savoir comment mapper (à titre d'exemple) a stringà a double.

Alors, quand vous convertissez-vous et quand lancez-vous? Dans les deux cas, nous avons une variable d'un type, disons A, et nous voulons avoir une variable de type B. Si notre objet A vraiment, en fait, sous le capot, est un B, alors nous castons. Si ce n'est pas vraiment un B, nous devons le convertir et définir comment le programme est censé obtenir un B à partir d'un A.


Dans un article de SO, Eric Lippert a mentionné qu'il n'y a pas de telle chose appelée distribution implicite et que c'est une conversion implicite . J'utilise la distribution et la conversion de manière interchangeable. qu'y a-t-il de mal à dire «distribution implicite»? N'est-ce pas si la conversion est implicite sans nécessiter de conversion, on peut dire que c'est une "distribution implicite"?
rahulaga_dev

1
@RahulAgarwal Ce qu'est un cast est une opération dans laquelle vous devez indiquer explicitement qu'un type donné est (ou peut être transformé en) une instance valide d'un autre type. Lorsqu'une conversion implicite existe, aucune conversion n'est nécessaire pour traiter le type comme un autre type. Donc, dire "cast implicite" n'a pas vraiment de sens (sauf pour les quelques situations comme Eric a mentionné où un opérateur de cast est ajouté sans que le développeur ne le tape, comme lors de l'utilisation de a foreach). En dehors de ces exceptions, les moulages sont par définition explicites.
Servy

5

De MSDN:

Conversions explicites (casts): les conversions explicites nécessitent un opérateur de conversion. La diffusion est requise lorsque des informations peuvent être perdues lors de la conversion ou lorsque la conversion peut échouer pour d'autres raisons. Les exemples typiques incluent la conversion numérique en un type qui a moins de précision ou une plage plus petite, et la conversion d'une instance de classe de base en classe dérivée.

Prenons l'exemple suivant:

double a = 2548.3;
int b;
b = (int)a; //2548 --> information (.3) lost in the conversion

Et aussi:

Un cast est un moyen d'informer explicitement le compilateur que vous avez l'intention d'effectuer la conversion et que vous êtes conscient qu'une perte de données peut se produire.

Vous pouvez utiliser la System.Convertclasse lorsque vous souhaitez effectuer une conversion entre des types non compatibles . La principale différence entre la diffusion et la conversion est la compilation et l' exécution . Les exceptions de conversion de type sont apparues au moment de l' exécution , c'est -à- dire qu'un cast de type qui échoue au moment de l'exécution provoquera la InvalidCastExceptionlevée d'un.


Conclusion: lors du casting, vous indiquez au compilateur qui aest vraiment de type bet si tel est le cas, le projet se construit sans aucune erreur comme cet exemple:

double s = 2;
int a = (int) s;

Mais dans la conversion vous dites au compilateur , il est un moyen de créer un nouvel objet à partir adu type b, s'il vous plaît le faire et projet construit sans erreur , mais comme je le disais si le type cast échoue à l' exécution, il fera un InvalidCastExceptionà être jeté .

Par exemple, le code ci-dessous n'est jamais compilé car le compilateur détecte que ne peut pas convertir une expression de type DateTimeen type int:

DateTime s = DateTime.Now;
int a = (int)(s);

Mais celui-ci est compilé avec succès:

DateTime s = DateTime.Now;
int a = Convert.ToInt32(s);

Mais au moment de l'exécution, vous obtiendrez InvalidCastExceptionce qui dit:

Cast non valide de «DateTime» vers «Int32».


4

La Convert.Doubleméthode appelle en fait la méthode en interne Double.Parse(string).

Ni le Stringtype ni le Doubletype ne définissent une conversion explicite / implicite entre les deux types, donc la conversion échouera toujours.

La Double.Parseméthode examinera chaque caractère du stringet créera une valeur numérique basée sur les valeurs des caractères du string. Si l'un des caractères n'est pas valide, la Parseméthode échoue (ce qui entraîne également l' Convert.Doubleéchec de la méthode).


1
Et en quoi cela diffère-t-il d'un casting explicite?

3
Un cast explicite ne regarde pas quel est le type de données, il regarde simplement les octets. Un exemple serait de transtyper char x = '1' en entier, l'entier serait 49 parce que le caractère '1' est # 49 dans la table ascii
user1751547

@ user1751547 Alors, l'utilisateur d'un Convert.ToDouble()regard au-delà des octets et prendrait -il en compte les données?

@ user1751547 Je pense que c'est le genre d'intuition qui est nécessaire pour répondre correctement à cette question. Dire simplement «ce n'est pas défini» est un peu discutable.
Ant P

@ edmastermind29 Oui, il regarderait le type d'entrée, et s'il s'agissait d'une chaîne, il passerait par chaque caractère, sachant que si la valeur ascii du caractère était 49, alors c'est le caractère '1' et le convertirait correctement
user1751547

3

Dans votre exemple, vous essayez de convertir une chaîne en un double (type non intégral).

Une conversion explicite est nécessaire pour que cela fonctionne.

Et je dois souligner que vous auriez pu utiliser Convert.ToDoubleau lieu de Convert.ToInt64car vous pouvez perdre les parties fractionnaires de la valeur double lorsque vous convertissez en un entier.

si votre variable a la valeur «5,25» varDouble aurait été 5,00 (perte de 0,25 à cause de la conversion en Int64)

Pour répondre à votre question sur la diffusion et la conversion.

Votre distribution (une distribution explicite) ne répond pas aux exigences d'une distribution explicite. la valeur que vous essayez de convertir avec l'opérateur de conversion n'est pas valide (c'est-à-dire non intégrale).

Visitez cette page MSDN pour les règles de diffusion / conversions


@ edmastermind29 j'ai mis à jour ma réponse. j'espère que cela répond à votre question.
scartag

Quelles sont les exigences pour un casting explicite ... par rapport à ma question? S'agit-il de la valeur «non intégrale»?

@ edmastermind29 Oui. si la valeur que vous essayez de convertir en type numérique n'est pas numérique, la conversion n'est pas valide. une conversion est requise.
scartag

3

La diffusion n'implique aucune conversion, c'est-à-dire que la représentation interne d'une valeur n'est pas modifiée. Exemple:

object o = "Hello"; // o is typed as object and contains a string.
string s = (string)o; // This works only if o really contains a string or null.

Vous pouvez convertir un doubleà stringcomme celui - ci

double d = 5;
string s = d.ToString(); // -> "5"

// Or by specifying a format
string formatted = d.ToString("N2"); // -> "5.00"

Vous pouvez convertir a stringen a doublede plusieurs manières (ici seulement deux d'entre elles):

string s = "5";
double d = Double.Parse(s); // Throws an exception if s does not contain a valid number

Ou la manière sûre

string s = "5";
double d;
if (Double.TryParse(s, out d)) {
    Console.WriteLine("OK. Result = {0}", d);
} else {
    Console.WriteLine("oops!");
}

Convert.ToDouble()appels en interneDouble.Parse() . Est-ce à mon avantage d'utiliser Convert.ToDouble()plus Double.Parse()ou pas et pourquoi?

Convert.ToDoublea beaucoup de surcharges qui acceptent différents types d'entrée. La surcharge acceptant les stringretours 0.0si une nullchaîne est passée. En dehors de cela, je ne vois aucun avantage à l'utiliser.
Olivier Jacot-Descombes

Alors, soit ou ... ou Double.Parse()a quelque chose à offrir que je devrais envisager?

Double.Parse()est plus direct que Convert.ToDouble(). Si vous êtes sûr que votre chaîne contiendra un nombre valide, vous pouvez l'utiliser en toute sécurité, sinon je vous conseille de l'utiliser Double.TryParse.
Olivier Jacot-Descombes

1
string variable = "5.00";     
double varDouble = (double)variable;

La conversion ci-dessus n'est tout simplement pas autorisée par la langue. Voici une liste de casts explicites pour les types numériques: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx Comme vous pouvez le voir, même tous les types numériques ne peuvent pas être convertis en un autre type numérique

Quelques informations supplémentaires sur la diffusion ici

Et en quoi cela diffère-t-il de Convert.ToDouble ()?

Lorsque vous castez un type, la structure des données n'est pas modifiée. Eh bien, en cas de conversion de valeurs numériques, vous risquez de perdre quelques bits ou d'obtenir quelques 0 bits supplémentaires. Mais vous travaillez toujours avec un certain nombre. Vous modifiez simplement une quantité de mémoire prise par ce nombre. C'est suffisamment sûr pour que le compilateur fasse tout ce qui est nécessaire.

Mais lorsque vous essayez de convertir une chaîne en un nombre, vous ne pouvez pas le faire car il ne suffit pas de modifier la quantité de mémoire prise par la variable. Par exemple, 5,00comme une chaîne est une séquence de "nombres": 53 (5) 46 (.) 48 (0) 48 (0) - c'est pour ASCII, mais la chaîne contiendra quelque chose de similaire. Si le compilateur prend juste les N premiers octets (4 pour le double? Pas sûr) d'une chaîne - ce morceau contiendra un nombre double complètement différent. En même temps, Convert.ToDouble () exécute un algorithme spécial qui prend chaque symbole d'une chaîne, détermine le chiffre qu'il représente et crée un double nombre pour vous, si la chaîne représente un nombre. Des langages comme PHP appelleront, grosso modo, Convert.ToDouble pour vous en arrière-plan. Mais C #, comme un langage typé statiquement, ne le fera pas pour vous. Cela vous permet d'être sûr que toute opération est de type sécurisé et que vous n'obtiendrez pas quelque chose d'inattendu en faisant quelque chose comme:

double d = (double)"zzzz"

@ edmastermind29 voir ma réponse mise à jour. J'ai essayé de l'expliquer. L'explication est loin d'être parfaite, mais supposons qu'elle explique la différence.
Viktor S.

1

Le cast d'une chaîne en un double comme celui-ci n'est pas autorisé C #, c'est pourquoi vous obtenez une exception, vous devez avoir la chaîne convertie ( document MSDN qui montre les chemins de conversion acceptables). C'est simplement parce qu'une chaîne ne va pas nécessairement contenir des données numériques, mais les différents types numériques le feront (sauf les valeurs nulles). A Convertexécutera une méthode qui vérifiera la chaîne pour voir si elle peut être transformée en valeur numérique. Si c'est possible, il renverra cette valeur. S'il ne peut pas, il lèvera une exception.

Pour le convertir, vous avez plusieurs options. Vous avez utilisé la Convertméthode dans votre question, il y en a Parsequi est en grande partie similaire à Convert, mais vous devriez également regarder TryParse qui vous permettrait de faire:

string variable = "5.00"; 

double varDouble;

if (Double.TryParse(variable, out varDouble)) {
    //Code that runs if the conversion succeeded.
} else {
    //Code that runs if the conversion failed.
}

Cela évite l'exception possible si vous essayez d' Convertutiliser Parseune chaîne non numérique.


Est-ce à mon avantage d'utiliser un TryParseover Convertcar TryParsevérifie si la conversion réussit?

@ edmastermind29 Je pense que oui. Convert lèvera une exception si la conversion échoue. TryParse renverra un booléen, True si la conversion réussit et False si elle échoue.
Keen

1

double varDouble = (double)variablesuppose que variablec'est déjà un double. Si ce variablen'est pas un double (c'est une chaîne), cela échouera. double varDouble = Convert.ToDouble(variable)fait comme il dit - il convertit. S'il peut analyser ou extraire un double, variableil le fera.

Je seconde en utilisant Double.Parseou Double.TryParseparce qu'il indique plus clairement ce qui est censé se passer. Vous commencez par une chaîne et vous vous attendez à ce qu'elle soit convertible en double. En cas de doute, utilisez TryParse.

Si variableest un argument de méthode, changez le type en double. Rendre l'appelant responsable de fournir le type correct. De cette façon, le compilateur fait le travail pour vous.


-1

La différence la plus importante est que si la conversion de type est utilisée et que la conversion échoue (disons que nous convertissons une très grande valeur flottante en int), aucune exception ne sera lancée et la valeur minimale qu'un int peut contenir sera affichée. Mais en cas d'utilisation de Convert , une exception sera levée pour de tels scénarios.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.