Unterschied zwischen Casting und Verwendung der Convert.To () -Methode


85

Ich habe eine Funktion, die a doubleauf stringWerte wirft .

string variable = "5.00"; 

double varDouble = (double)variable;

Eine Codeänderung wurde eingecheckt und das Projekt wird mit dem Fehler erstellt: System.InvalidCastException: Specified cast is not valid.

Nachdem Sie jedoch Folgendes getan haben ...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

... das Projekt fehlerfrei erstellt wird.

Was ist der Unterschied zwischen Gießen und Verwenden der Convert.To()Methode? Warum wirft Casting ein Exceptionund benutzt das Convert.To()nicht?

c#  casting 


6
In Bezug auf eine Frage , auf die verwiesen wird , fragt das OP, wann eine Besetzung oder Konvertierung verwendet werden soll, und in der akzeptierten Antwort heißt es: "Es ist wirklich eine Frage der Wahl, was auch immer Sie verwenden." Ich frage nach dem Unterschied zwischen einer Besetzung und einem Konvertiten. Meiner Meinung nach bieten die folgenden Antworten (Lob SO!) Weitere Details zu den Unterschieden im Vergleich zu "Verwenden dieses oder jenes nach Wahl" ... und dieses Detail könnte im Wesentlichen verwendet werden, um eine fundiertere Auswahl zu treffen.

@ edmastermind29 Es gibt keinen großen Unterschied zwischen "Was ist der Unterschied zwischen x und y" und "wann x und y verwendet werden sollen" im Programmierkontext. Beide antworten sich gegenseitig.
Nawfal

2
Fast 3 Jahre später scheint es in diesem Fall nicht so zu sein, dass sich einer gegenseitig antwortet. F: "Was ist der Unterschied zwischen X und Y?" A: "Es ist wirklich eine Frage der Wahl, was auch immer Sie verwenden." Nicht sehr nützlich.

Niemand scheint eine direkte Antwort darauf zu haben, welche Leistung am besten ist. Dies ist auch Teil der Frage. Aus meiner Erfahrung ist Cast besser, insbesondere wenn es darum geht, solche Spaltenwerte zu erhalten. (Int) datatable.Rows [0] [0], if Wir wissen, dass es 100% int
Sundara Prabu

Antworten:


122

Auch wenn Sie können sie irgendwie als gleichwertig sehen sind sie in Zweck völlig anders. Versuchen wir zunächst zu definieren, was eine Besetzung ist:

Beim Casting wird eine Entität eines Datentyps in eine andere geändert.

Es ist ein bisschen generisch und entspricht irgendwie einer Konvertierung, da Cast oft die gleiche Syntax wie eine Konvertierung hat. Daher sollte die Frage lauten, wann eine Besetzung (implizit oder explizit) von der Sprache zugelassen wird und wann Sie eine (mehr) verwenden müssen. explizite Konvertierung?

Lassen Sie mich zunächst zeichnen eine einfache Linie zwischen ihnen. Formal (auch wenn dies für die Sprachsyntax gleichwertig ist) ändert eine Besetzung den Typ, während eine Konvertierung den Wert ändert (möglicherweise zusammen mit dem Typ). Auch ein Cast ist reversibel, während die Konvertierung möglicherweise nicht möglich ist.

Dieses Thema ist ziemlich umfangreich. Versuchen wir also, ein wenig einzugrenzen, indem wir benutzerdefinierte Darsteller aus dem Spiel ausschließen.

Implizite Besetzungen

In C # ist eine Umwandlung implizit, wenn Sie keine Informationen verlieren (bitte beachten Sie, dass diese Prüfung mit Typen und nicht mit ihren tatsächlichen Werten durchgeführt wird ).

Primitive Typen

Beispielsweise:

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

Diese Casts sind implizit, da Sie während der Konvertierung keine Informationen verlieren (Sie machen den Typ nur breiter). Umgekehrt ist implizite Umwandlung nicht zulässig, da Sie bei der Konvertierung möglicherweise Informationen verlieren, unabhängig von ihren tatsächlichen Werten (da sie nur zur Laufzeit überprüft werden können). Zum Beispiel wird dieser Code nicht kompiliert, weil a doublemöglicherweise einen Wert enthält (und tatsächlich tut), der nicht mit a dargestellt werden kann float:

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

Objekte

Im Fall eines Objekts (eines Zeigers auf) ist die Umwandlung immer implizit, wenn der Compiler sicher sein kann, dass der Quelltyp eine abgeleitete Klasse ist (oder den Typ der Zielklasse implementiert), zum Beispiel:

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

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

In diesem Fall weiß der Compiler , dass stringimplementiert wird IFormattableund das NotSupportedExceptionheißt (abgeleitet von), Exceptionso dass die Umwandlung implizit ist. Es gehen keine Informationen verloren, da Objekte ihren Typ nicht ändern (dies unterscheidet sich von structs und primitiven Typen, da Sie mit einer Besetzung ein neues Objekt eines anderen Typs erstellen ). Was sich ändert, ist Ihre Ansicht von ihnen.

Explizite Besetzungen

Eine Umwandlung ist explizit, wenn die Konvertierung nicht implizit vom Compiler durchgeführt wird und Sie dann den Besetzungsoperator verwenden müssen. Normalerweise bedeutet dies:

  • Sie können Informationen oder Daten verlieren, daher müssen Sie sich dessen bewusst sein.
  • Die Konvertierung schlägt möglicherweise fehl (da Sie einen Typ nicht in den anderen konvertieren können). Sie müssen also erneut wissen, was Sie tun.

Primitive Typen

Für primitive Typen ist eine explizite Umwandlung erforderlich, wenn Sie während der Konvertierung einige Daten verlieren können, zum Beispiel:

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

float epsilon = (float)Double.Epsilon;

In beiden Beispielen gehen floatInformationen verloren (in diesem Fall Genauigkeit) , selbst wenn die Werte in den Bereich fallen, sodass die Konvertierung explizit sein muss. Versuchen Sie jetzt Folgendes:

float max = (float)Double.MaxValue;

Diese Konvertierung schlägt fehl. Sie muss also explizit sein, damit Sie sich dessen bewusst sind und eine Überprüfung durchführen können (im Beispiel ist der Wert konstant, er kann jedoch aus einigen Laufzeitberechnungen oder E / A stammen). Zurück zu Ihrem Beispiel:

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

Dies wird nicht kompiliert, da der Compiler keinen Text in Zahlen konvertieren kann. Text kann beliebige Zeichen enthalten, nicht nur Zahlen, und dies ist in C # zu viel, selbst für eine explizite Besetzung (aber möglicherweise in einer anderen Sprache zulässig).

Objekte

Die Konvertierung von Zeigern (in Objekte) kann fehlschlagen, wenn Typen keine Beziehung zueinander haben. Beispielsweise wird dieser Code nicht kompiliert (da der Compiler weiß, dass keine Konvertierung möglich ist):

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

Dieser Code wird kompiliert , aber es kann zur Laufzeit nicht (es hängt von der effektiven Art der gegossenen Objekte) mit einem InvalidCastException:

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

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

Konvertierungen

Also, wenn Casts Konvertierung sind, warum brauchen wir dann Klassen wie Convert? Ignorieren Sie subtile Unterschiede, die sich aus der ConvertImplementierung und den IConvertibleImplementierungen ergeben, weil Sie in C # mit einer Besetzung dem Compiler sagen:

Vertrauen Sie mir, dieser Typ ist dieser Typ, auch wenn Sie ihn jetzt nicht kennen, lassen Sie es mich tun und Sie werden sehen.

-oder-

Keine Sorge, es ist mir egal, dass bei dieser Konvertierung etwas verloren geht.

Für alles andere eine weitere explizite Operation erforderlich (man denke über Auswirkungen der einfachen Würfe , deshalb C ++ lange eingeführt, ausführliche und explizite Syntax für sie). Dies kann eine komplexe Operation beinhalten (für string-> doubleKonvertierung ist eine Analyse erforderlich). Eine Konvertierung in stringzum Beispiel ist immer möglich (über eine ToString()Methode), kann jedoch etwas anderes bedeuten als erwartet. Daher muss es expliziter sein als eine Besetzung ( mehr Sie schreiben, mehr denken Sie darüber nach, was Sie tun ).

Diese Konvertierung kann innerhalb des Objekts (unter Verwendung bekannter IL-Anweisungen dafür) unter Verwendung von benutzerdefinierten Konvertierungsoperatoren (die in der zu konvertierenden Klasse definiert sind) oder komplexeren Mechanismen ( TypeConverterz. B. oder Klassenmethoden) erfolgen. Sie wissen nicht, was passieren wird, aber Sie wissen, dass dies möglicherweise fehlschlägt (deshalb sollten Sie IMO verwenden, wenn eine kontrollierte Konvertierung möglich ist). In Ihrem Fall einfach die Konvertierung analysiert die stringein zu produzieren double:

double value = Double.Parse(aStringVariable);

Dies kann natürlich fehlschlagen. Wenn Sie dies tun, sollten Sie immer die Ausnahme abfangen, die es möglicherweise auslöst ( FormatException). Es ist hier nicht zum Thema, aber wenn a TryParseverfügbar ist, sollten Sie es verwenden (weil Sie semantisch sagen, dass es möglicherweise keine Zahl ist und es sogar noch schneller ist ... zu scheitern).

Konvertierungen in .NET können von vielen Stellen stammen, TypeConverterimplizite / explizite Casts mit benutzerdefinierten Konvertierungsoperatoren, Implementierung IConvertibleund Analyse von Methoden (habe ich etwas vergessen?). Weitere Informationen hierzu finden Sie in MSDN.

Um diese lange Antwort zu beenden, nur ein paar Worte zu benutzerdefinierten Konvertierungsoperatoren. Es ist nur Zucker , den Programmierer einen Cast verwenden zu lassen, um einen Typ in einen anderen umzuwandeln. Es ist eine Methode innerhalb einer Klasse (die, die gewirkt wird), die besagt: "Hey, wenn er / sie diesen Typ in diesen Typ konvertieren möchte, kann ich es tun." Beispielsweise:

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

In diesem Fall ist dies explizit, da es möglicherweise fehlschlägt, dies jedoch der Implementierung überlassen wird (auch wenn diesbezüglich Richtlinien bestehen). Stellen Sie sich vor, Sie schreiben eine benutzerdefinierte Zeichenfolgenklasse wie folgt:

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

In Ihrer Implementierung können Sie entscheiden, "das Leben des Programmierers zu vereinfachen" und diese Konvertierung über eine Besetzung verfügbar zu machen (denken Sie daran, dass dies nur eine Abkürzung ist, um weniger zu schreiben). Einige Sprachen erlauben dies möglicherweise sogar:

double value = "123";

Ermöglichen der impliziten Konvertierung in einen beliebigen Typ (Überprüfung wird zur Laufzeit durchgeführt). Mit geeigneten Optionen kann dies beispielsweise in VB.NET erfolgen. Es ist nur eine andere Philosophie.

Was kann ich mit ihnen machen?

Die letzte Frage ist also, wann Sie die eine oder andere verwenden sollten. Mal sehen, wann Sie eine explizite Besetzung verwenden können:

  • Konvertierungen zwischen Basistypen.
  • Konvertierungen von objectzu einem anderen Typ (dies kann auch das Unboxing einschließen).
  • Konvertierungen von einer abgeleiteten Klasse in eine Basisklasse (oder in eine implementierte Schnittstelle).
  • Konvertierungen von einem Typ in einen anderen über benutzerdefinierte Konvertierungsoperatoren.

Es kann nur die erste Konvertierung durchgeführt werden, Convertsodass Sie für die anderen keine Wahl haben und eine explizite Besetzung verwenden müssen.

Mal sehen, wann Sie verwenden können Convert:

  • Konvertierungen von einem beliebigen Basistyp in einen anderen Basistyp (mit einigen Einschränkungen siehe MSDN ).
  • Konvertierungen von jedem Typ, der IConvertiblein einen anderen (unterstützten) Typ implementiert wird .
  • Konvertierungen von / zu einem byteArray zu / von einer Zeichenfolge.

Schlussfolgerungen

IMO Convertsollte jedes Mal verwendet werden, wenn Sie wissen, dass eine Konvertierung fehlschlägt (aufgrund des Formats, des Bereichs oder weil sie möglicherweise nicht unterstützt wird), selbst wenn dieselbe Konvertierung mit einer Besetzung durchgeführt werden kann (sofern nichts anderes verfügbar ist). Es macht deutlich, wer Ihren Code lesen wird, was Ihre Absicht ist und dass er möglicherweise fehlschlägt (Vereinfachung des Debugs).

Für alles andere brauchen Sie eine Besetzung, keine Wahl, aber wenn eine andere bessere Methode verfügbar ist, empfehle ich Ihnen, sie zu verwenden. In Ihrem Beispiel ist eine Konvertierung von stringnach doubleetwas, das (insbesondere wenn Text vom Benutzer stammt) sehr oft fehlschlägt. Sie sollten es daher so deutlich wie möglich machen (außerdem erhalten Sie mehr Kontrolle darüber), beispielsweise mithilfe einer TryParseMethode.

Edit: Was ist der Unterschied zwischen ihnen?

Entsprechend der aktualisierten Frage und der Beibehaltung dessen, was ich zuvor geschrieben habe (etwa wann Sie eine Besetzung verwenden können, im Vergleich zu dem Zeitpunkt, zu dem Sie sie verwenden können / müssen Convert), ist der letzte Punkt, der geklärt werden muss, ob es Unterschiede zwischen ihnen gibt (außerdem ConvertVerwendungen IConvertibleund IFormattableSchnittstellen, damit Operationen ausgeführt werden können) nicht erlaubt mit Abgüssen).

Kurze Antwort ist ja, sie verhalten sich anders . Ich sehe die ConvertKlasse so oft wie eine Hilfsmethodenklasse, dass sie Vorteile oder leicht unterschiedliche Verhaltensweisen bietet . Beispielsweise:

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

Ganz anders, oder? Cast-Kürzungen (das erwarten wir alle) führen jedoch Converteine Rundung auf die nächste Ganzzahl durch (und dies ist möglicherweise nicht zu erwarten, wenn Sie sich dessen nicht bewusst sind). Jede Konvertierungsmethode führt zu Unterschieden, sodass eine allgemeine Regel nicht angewendet werden kann und sie von Fall zu Fall angezeigt werden müssen. 19 Basistypen zum Konvertieren in jeden anderen Typ ... Liste kann ziemlich lang sein, viel besser, um MSDN von Fall zu Fall zu konsultieren Fall!


Ich habe die Frage geändert, um zu stellen Difference between casting and using the Convert.To() method. Ansonsten sehr umfassende Antwort. (Ich hoffe, meine Frage wird wieder geöffnet ...)

@ edmastermind29 Ich habe die Frage ein wenig bearbeitet, das Thema ist selbst für eine lange Antwort zu lang (mehr als 300 mögliche Conversions zur Liste). Convert bietet Vorteile (oder nur unerwartete Verhaltensweisen?) Nicht nur gegenüber Casts, sondern auch gegenüber "einfachen" IConvertible- und IFormattable-Schnittstellen.
Adriano Repetti

Ich mag die von C entlehnte Vorstellung doublenicht, dass Werte, die keine ganzen Zahlen darstellen, in "konvertierbar" sein sollten int. Ein Abguss würde das entsprechende Paradigma in Fällen scheint , wo zB einen abruft Int32Wert von a , double[]die eine Mischung aus reellen Zahlen und hält Int32Werten, die umgewandelt wurde double[ein Versuch , einen Wert zu konvertieren , die nicht darstellbare ist gerade in int32einen unerwarteten Zustand anzeigen würde , und sollte eine Ausnahme auslösen], aber ich würde denken, wenn man eine verlustbehaftete Konvertierung will, sollte man spezifisch über die Form sein, die man will.
Supercat

1
Ein weiterer Unterschied besteht zwischen objektiven und primitiven Typen. zBobject o = 123; var l = Convert.ToInt64(o); var i = (long) (int) o; var f = (long) o // InvalidCastException
yue shi

1
@ rory.ap das ist ein wichtiger Punkt. Nein, formal ist das keine Besetzung ( float-> int), sondern ein Zwang . Eine Besetzung könnte zum Beispiel sein DerivedClass-> BaseClass. Es ist verwirrend, weil wir in C # für beide dasselbe Wort (und denselben Operator) verwenden, aber es handelt sich tatsächlich um unterschiedliche Dinge. Eine formale Definition zur Unterscheidung ist etwas komplizierter als das, was ich geschrieben habe.
Adriano Repetti

12

Casting ist eine Möglichkeit, dem Compiler zu sagen: "Ich weiß, dass Sie denken, dass diese Variable ein Balken ist, aber ich weiß zufällig mehr als Sie. Das Objekt ist tatsächlich ein Foo. Lassen Sie mich es also so behandeln, als wäre es ein Foo von." jetzt weiter. " Wenn sich dann zur Laufzeit herausstellt, dass das eigentliche Objekt wirklich ein Foo ist, funktioniert Ihr Code. Wenn sich herausstellt, dass das Objekt überhaupt kein Foo war, erhalten Sie eine Ausnahme. (Speziell ein System.InvalidCastException.)

Das Konvertieren ist eine Möglichkeit zu sagen: "Wenn Sie mir ein Objekt vom Typ Bar geben, kann ich ein brandneues Foo-Objekt erstellen, das darstellt, was sich in diesem Bar-Objekt befindet. Ich werde das ursprüngliche Objekt nicht ändern, es hat gewonnen." Wenn Sie das ursprüngliche Objekt nicht anders behandeln, wird etwas Neues erstellt, das nur auf einem anderen Wert basiert . Wie es das tun wird, kann alles sein. Im Falle eines Convert.ToDoubleAufrufs wird es am Ende aufgerufenDouble.ParseDas hat alle Arten von komplexer Logik, um zu bestimmen, welche Arten von Zeichenfolgen welche numerischen Werte darstellen. Sie können Ihre eigene Konvertierungsmethode schreiben, mit der Zeichenfolgen unterschiedlich doppelt zugeordnet werden (möglicherweise, um eine völlig andere Konvention für die Anzeige von Zahlen zu unterstützen, z. B. römische Ziffern oder was auch immer). Eine Konvertierung kann alles bewirken, aber die Idee ist, dass Sie den Compiler nicht wirklich bitten, etwas für Sie zu tun. Sie sind derjenige, der den Code schreibt, um zu bestimmen, wie das neue Objekt erstellt werden soll, da der Compiler ohne Ihre Hilfe nicht weiß, wie er (als Beispiel) a stringeinem zuordnen kann double.

Also, wann konvertierst du und wann wirfst du? In beiden Fällen haben wir eine Variable vom Typ A, sagen wir A, und wir möchten eine Variable vom Typ B. Wenn unser A-Objekt tatsächlich unter der Haube ein B ist, dann werfen wir. Wenn es nicht wirklich ein B ist, müssen wir es konvertieren und definieren, wie das Programm ein B von einem A erhalten soll.


In einem SO-Beitrag erwähnte Eric Lippert, dass es keine so genannte implizite Besetzung gibt und es sich um eine implizite Konvertierung handelt . Ich habe Cast und Conversion austauschbar verwendet. Was ist falsch daran, "implizite Besetzung" zu sagen? Wenn Konvertierung nicht implizit ist, ohne dass eine Besetzung erforderlich ist, kann man sagen, dass es sich um eine "implizite Besetzung" handelt?
rahulaga_dev

1
@RahulAgarwal Was eine Besetzung ist, ist eine Operation, bei der Sie explizit angeben müssen, dass ein bestimmter Typ eine gültige Instanz eines anderen Typs ist (oder daraus gemacht werden kann). Wenn eine implizite Konvertierung vorhanden ist, ist keine Umwandlung erforderlich , um den Typ als einen anderen Typ zu behandeln. "Implizite Besetzung" zu sagen ist also nicht wirklich sinnvoll (außer in den wenigen Situationen, in denen Eric erwähnt hat, dass ein Besetzungsoperator hinzugefügt wird, ohne dass der Entwickler ihn eingibt, wie bei Verwendung von a foreach). Außerhalb dieser Ausnahmen sind Abgüsse per Definition explizit.
Servy

4

Die Convert.DoubleMethode ruft die Double.Parse(string)Methode eigentlich nur intern auf .

Weder der StringTyp noch der DoubleTyp definieren eine explizite / implizite Konvertierung zwischen den beiden Typen, sodass das Casting immer fehlschlägt.

Die Double.ParseMethode betrachtet jedes Zeichen in der stringund erstellt einen numerischen Wert basierend auf den Werten der Zeichen in der string. Wenn eines der Zeichen ungültig ist, Parseschlägt die Methode fehl (was dazu führt, dass die Convert.DoubleMethode ebenfalls fehlschlägt).


1
Und wie unterscheidet sich das von einer expliziten Besetzung?

3
Bei einer expliziten Umwandlung wird nicht der Datentyp, sondern nur die Bytes betrachtet. Ein Beispiel wäre das Umwandeln von char x = '1' in eine Ganzzahl, die Ganzzahl wäre 49, da der Cahracter '1' in der ASCII-Tabelle # 49 ist
user1751547

@ user1751547 Würde der Benutzer eines Convert.ToDouble()Blicks über Bytes hinaus die Daten berücksichtigen?

@ user1751547 Ich denke, das ist die Art von Intuition, die erforderlich ist, um diese Frage richtig zu beantworten. Einfach zu sagen "es ist nicht definiert" ist ein wenig umstritten.
Ant P

@ edmastermind29 Ja, es würde sich den Eingabetyp ansehen, und wenn es eine Zeichenfolge wäre, würde es jedes Zeichen durchlaufen, wissend, dass wenn der ASCII-Wert des Zeichens 49 wäre, es das '
1'

3

In Ihrem Beispiel versuchen Sie, eine Zeichenfolge in ein Double umzuwandeln (nicht integraler Typ).

Eine explizite Konvertierung ist erforderlich, damit es funktioniert.

Und ich muss darauf hinweisen, dass Sie Convert.ToDoublestattdessen hätten verwenden Convert.ToInt64können, da Sie die Bruchteile des doppelten Werts verlieren können, wenn Sie in ein int konvertieren.

Wenn Ihre Variable den Wert "5.25" hat, wäre varDouble 5.00 gewesen (Verlust von 0.25 aufgrund der Konvertierung in Int64).

Um Ihre Frage zu Casting vs Converting zu beantworten.

Ihre Besetzung (eine explizite Besetzung) erfüllt nicht die Anforderungen für eine explizite Besetzung. Der Wert, den Sie mit dem Cast-Operator umwandeln möchten, ist ungültig (dh nicht ganzzahlig).

Auf dieser MSDN-Seite finden Sie die Regeln für Casting / Conversions


@ edmastermind29 Ich habe meine Antwort aktualisiert. Ich hoffe, es beantwortet Ihre Frage.
Scartag

Was sind die Voraussetzungen für eine explizite Besetzung ... im Zusammenhang mit meiner Frage? Ist es in Bezug auf den "nicht integralen" Wert?

@ edmastermind29 Ja. Wenn der Wert, den Sie in einen numerischen Typ umwandeln möchten, nicht numerisch ist, ist die Umwandlung ungültig. Eine Konvertierung ist erforderlich.
Scartag

3

Das Casting beinhaltet keine Konvertierung, dh die interne Darstellung eines Wertes wird nicht geändert. Beispiel:

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.

Sie können konvertieren eine doublezu stringdieser mag

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

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

Sie können a stringauf doubleverschiedene Arten in a konvertieren (hier nur zwei davon):

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

Oder auf sichere Weise

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

Convert.ToDouble()intern anruftDouble.Parse() . Ist es zu meinem Vorteil, Convert.ToDouble()über zu verwenden Double.Parse()oder nicht und warum?

Convert.ToDoublehat viele Überladungen, die verschiedene Arten von Eingaben akzeptieren. Die Überlastung der Annahme stringzurückkehrt , 0.0wenn eine nullZeichenfolge übergeben wird. Abgesehen davon sehe ich keinen Vorteil darin, es zu benutzen.
Olivier Jacot-Descombes

Also, entweder oder ... oder hat Double.Parse()etwas zu bieten, das ich berücksichtigen sollte?

Double.Parse()ist direkter als Convert.ToDouble(). Wenn Sie sicher sind, dass Ihre Zeichenfolge eine gültige Nummer enthält, können Sie diese sicher verwenden. Andernfalls empfehle ich Ihnen, sie zu verwenden Double.TryParse.
Olivier Jacot-Descombes

3

Von MSDN:

Explizite Konvertierungen (Casts): Explizite Conversions erfordern einen Cast-Operator. Casting ist erforderlich, wenn Informationen bei der Konvertierung verloren gehen oder wenn die Konvertierung aus anderen Gründen möglicherweise nicht erfolgreich ist. Typische Beispiele sind die numerische Konvertierung in einen Typ mit geringerer Genauigkeit oder einem kleineren Bereich sowie die Konvertierung einer Basisklasseninstanz in eine abgeleitete Klasse.

Betrachten Sie das folgende Beispiel:

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

Und auch:

Eine Besetzung ist eine Möglichkeit, den Compiler explizit darüber zu informieren, dass Sie die Konvertierung durchführen möchten und dass Sie wissen, dass Datenverluste auftreten können.

Sie können System.Convertclass verwenden, wenn Sie zwischen nicht kompatiblen Typen konvertieren möchten . Der Hauptunterschied zwischen Casting und Konvertierung besteht in Kompilierung und Laufzeit . Die Ausnahmen für die Typkonvertierung werden zur Laufzeit angezeigt . Das heißt, eine zur Laufzeit fehlgeschlagene Typumwandlung führt dazu, dass eine InvalidCastExceptionausgelöst wird.


Fazit: Beim Casting teilen Sie dem Compiler mit, dass aes sich wirklich um einen Typ handelt, bund wenn ja, wird das Projekt ohne Fehler wie in diesem Beispiel erstellt:

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

Aber bei der Konvertierung, die Sie dem Compiler sagen, gibt es eine Möglichkeit, ein neues Objekt vom aTyp zu erstellen. Führenb Sie dies aus und erstellen Sie Projekte ohne Fehler. Wie ich bereits sagte, wenn die Typumwandlung zur Laufzeit fehlschlägt, führt dies zu einem InvalidCastExceptionto geworfen werden .

Zum Beispiel wird der folgende Code niemals kompiliert, da der Compiler erkennt, dass ein Ausdruck vom Typ nicht DateTimein einen Typ umgewandelt werden kann int:

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

Aber dieser ist erfolgreich kompiliert:

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

Aber zur Laufzeit erhalten Sie InvalidCastExceptionFolgendes:

Ungültige Umwandlung von 'DateTime' in 'Int32'.


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

Die oben genannte Konvertierung ist von der Sprache einfach nicht zulässig. Hier ist eine Liste expliziter Umwandlungen für numerische Typen: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx Wie Sie sehen, konnte nicht jeder numerische Typ in einen anderen numerischen Typ konvertiert werden

Weitere Infos zum Casting hier

Und wie unterscheidet sich das von Convert.ToDouble ()?

Wenn Sie einen Typ umwandeln, wird die Datenstruktur nicht geändert. Nun, im Falle einer Konvertierung numerischer Werte können Sie einige Bits verlieren oder einige zusätzliche 0 Bits erhalten. Aber Sie arbeiten immer noch mit einer Nummer. Sie ändern nur die von dieser Nummer belegte Speichermenge. Das ist sicher genug, damit der Compiler alles Notwendige tun kann.

Wenn Sie jedoch versuchen, eine Zeichenfolge in eine Zahl umzuwandeln, können Sie dies nicht tun, da es nicht ausreicht, die von der Variablen belegte Speichermenge zu ändern. Zum Beispiel 5.00als Zeichenfolge ist eine Folge von "Zahlen": 53 (5) 46 (.) 48 (0) 48 (0) - das ist für ASCII, aber die Zeichenfolge enthält etwas Ähnliches. Wenn der Compiler nur die ersten N (4 für doppelt? Nicht sicher) Bytes aus einer Zeichenfolge nimmt, enthält dieses Stück eine völlig andere doppelte Zahl. Gleichzeitig führt Convert.ToDouble () einen speziellen Algorithmus aus, der jedes Symbol einer Zeichenfolge verwendet, die Ziffer herausfindet, die es darstellt, und eine doppelte Zahl für Sie erstellt, wenn die Zeichenfolge eine Zahl darstellt. Sprachen wie PHP rufen im Hintergrund ungefähr Convert.ToDouble für Sie auf. Aber C # wird das wie eine statisch typisierte Sprache nicht für Sie tun. Auf diese Weise können Sie sicher sein, dass jede Operation typsicher ist und Sie nichts Unerwartetes erhalten, wenn Sie Folgendes tun:

double d = (double)"zzzz"

@ edmastermind29 siehe meine aktualisierte Antwort. Ich habe versucht, es zu erklären. Die Erklärung ist alles andere als perfekt, aber nehmen wir an, sie erklärt den Unterschied.
Viktor S.

1

Das Umwandeln eines Strings in ein solches Double ist nicht zulässig. C # Aus diesem Grund erhalten Sie eine Ausnahme. Sie müssen den String konvertieren lassen ( MSDN-Dokument , das akzeptable Konvertierungspfade anzeigt). Dies liegt einfach daran, dass eine Zeichenfolge nicht unbedingt numerische Daten enthalten muss, sondern die verschiedenen numerischen Typen (mit Ausnahme von Nullwerten). EINConvert führt eine Methode aus, die die Zeichenfolge überprüft, um festzustellen, ob sie in einen numerischen Wert umgewandelt werden kann. Wenn dies möglich ist, wird dieser Wert zurückgegeben. Wenn dies nicht möglich ist, wird eine Ausnahme ausgelöst.

Um es zu konvertieren, haben Sie mehrere Möglichkeiten. Sie haben die ConvertMethode in Ihrer Frage verwendet, Parsedie weitgehend ähnlich ist Convert, aber Sie sollten sich auch TryParse ansehen, mit der Sie Folgendes tun können:

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.
}

Dies vermeidet die mögliche Ausnahme sollten Sie versuchen, Convertoder Parseeine nicht-numerische Zeichenfolge.


Ist es zu meinem Vorteil, ein TryParseOver zu verwenden, Convertweil TryParseüberprüft wird, ob die Konvertierung erfolgreich ist?

@ edmastermind29 Ich denke schon. Convert löst eine Ausnahme aus, wenn die Konvertierung fehlschlägt. TryParse gibt einen Booleschen Wert zurück, True, wenn die Konvertierung erfolgreich ist, und False, wenn sie fehlschlägt.
Keen

1

double varDouble = (double)variablegeht davon aus, dass variabledas schon ein Doppel ist. Wenn variablees sich nicht um ein Double handelt (es handelt sich um eine Zeichenfolge), schlägt dies fehl. double varDouble = Convert.ToDouble(variable)mag es sagt - es konvertiert. Wenn es ein Double analysieren oder auf andere Weise extrahieren kannvariable kann, wird es.

Ich benutze Double.Parseoder Double.TryParseweil es deutlicher anzeigt, was passieren soll. Sie beginnen mit einer Zeichenfolge und erwarten, dass diese in eine doppelte konvertierbar ist. Wenn Sie Zweifel haben, verwenden Sie TryParse.

Wenn variablees sich um ein Methodenargument handelt, ändern Sie den Typ in double. Machen Sie den Anrufer für die Bereitstellung des richtigen Typs verantwortlich. Auf diese Weise erledigt der Compiler die Arbeit für Sie.


-1

Der wichtigste Unterschied ist , dass , wenn Typumwandlung verwendet wird , und die Konvertierung fehlschlägt (sagt wir einen sehr großen Schwimmer Wert int Umwandlung) keine Ausnahme ausgelöst und ein int des Minimalwert gezeigt , werden wird halten. Bei Verwendung von Convert wird für solche Szenarien jedoch eine Ausnahme ausgelöst.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.