Frage

In Jesse Liberty # Buch Learning C, sagt er, „Objekte eines Typs in Objekte eines anderen Typs umgewandelt werden können. Dies wird Casting genannt.“

Wenn Sie die IL aus dem folgenden Code erzeugt untersuchen, kann man deutlich sehen, dass die gegossene Zuordnung ist nicht das Gleiche wie die konvertierte Zuordnung zu tun. Im ersteren können Sie die Boxen / Unboxing sehen auftritt; in letzterem können Sie einen Anruf zu einer convert-Methode.

ich weiß, am Ende kann es nur ein dummer semantischer Unterschied - aber nur ein anderes Wort für die Umwandlung werfe. Ich meine nicht, snarky zu sein, aber ich bin nicht daran interessiert, in niemandes Bauchgefühl auf diesem - Meinungen zählen nicht hier! Kann jemand zu einem endgültigen Bezugspunkt, oder verweigert bestätigt, wenn Gießen und Umwandlung sind die gleiche Sache?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

Danke

rp

Hinweis hinzugefügt, nachdem Matt Kommentar über explizite / implizite:

Ich glaube nicht, implizite / explizite der Unterschied ist. Im Code, den ich geschrieben, ist die Änderung in beiden Fällen explizit. Eine implizite Konvertierung ist, was geschieht, wenn Sie einen kurzen in einen int zuweisen.

Hinweis auf Sklivvz:

Ich wollte die Bestätigung, dass mein Verdacht der Lockerheit des Jesse Liberty (sonst in der Regel klar und deutlich) Sprache richtig war. Ich dachte, dass Jesse Liberty wurde mit seiner Sprache ein wenig locker zu sein. Ich verstehe, dass Gießen in Objekthierarchie geführt wird - d. H, kann man nicht von einer ganzen Zahl in eine Zeichenfolge, aber Sie von benutzerdefinierter Ausnahme von System.Exception zu einem System.Exception abgeleitet werfen könnten.

Es ist interessant, aber, dass, wenn Sie von einem int in einen String zu werfen versuchen die Compiler Dir sagt, dass es kann nicht „umwandeln“, um den Wert. Vielleicht Jesse ist richtiger als ich dachte!

War es hilfreich?

Lösung

Die einfache Antwort lautet:. Es hängt

Für Werttypen werden Casting beinhalten wirklich es auf eine andere Art zu konvertieren. Zum Beispiel:

float f = 1.5f;
int i = (int) f; // Conversion

Wenn der Guss Ausdruck unboxes, das Ergebnis (vorausgesetzt, es funktioniert) ist in die Regel nur eine Kopie das, was in der Box war, mit dem gleichen Typ. Es gibt Ausnahmen, aber - man von einem boxed int zu einem Enum unbox kann (mit einem zugrunde liegenden Typ int) und umgekehrt; Ebenso können Sie aus einem boxed int zu einem Nullable unbox .

Wenn der Guss Ausdruck von einem Referenztyp in einen anderen und keine benutzerdefinierten Umwandlung beteiligt ist, gibt es keine Konvertierung so weit wie das Objekt selbst betrifft - nur die Art der Hinweis „Änderungen "- und das ist eigentlich nur die Art und Weise, dass der Wert angesehen wird, eher als die Referenz selbst (die die gleichen Bits wie zuvor sein werden). Zum Beispiel:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

Wenn benutzerdefinierte Konvertierungen einlassen, diese in der Regel bringt ein anderes Objekt / Wert zurück. Zum Beispiel könnten Sie eine Umwandlung in String für Ihre eigene Art definieren - und  dies würde sicherlich nicht die gleichen Daten wie Ihr eigenes Objekt sein. (Es könnte eine vorhandene Zeichenfolge sein, von Ihrem Objekt bereits erwähnte, natürlich.) Nach meiner Erfahrung benutzerdefinierte Konvertierungen existieren in der Regel zwischen Werttypen eher als Referenztyp, so ist dies selten ein Problem.

Alle diese gelten als Umwandlungen in Bezug auf die Spezifikation - aber sie haben nicht alle zählen als Umwandlung eines Objekt in eine Objekt eines anderen Typs. Ich vermute, dies ist ein Fall von Jesse Liberty mit Terminologie ist lose - ich habe bemerkt, dass in Programmieren mit C # 3.0, die wir lesen gerade haben

.

Ist das alles abdecken?

Andere Tipps

Absolut nicht!

Convert versucht Ihr eine Int32 zu erhalten über „alle Mittel“. Guss tut nichts dergleichen. Mit den Darstellern teilen Sie den Compiler das Objekt als Int, ohne Konvertierung zu behandeln.

Sie sollten immer Besetzung verwenden, wenn Sie (mit Absicht) wissen, dass das Objekt ein Int32 oder eine andere Klasse, die einen Casting-Operator zu Int32 (wie Schwimmer, zum Beispiel) hat.

Convert sollte mit String oder mit anderen Klassen verwendet werden.

Versuchen Sie, diese

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

Ergebnis:

  

9223372036854775807

     

255

     

Unbehandelte Ausnahme:

     

System.OverflowException: Wert ist   größer ist als Byte.MaxValue oder weniger   als Byte.MinValue bei   System.Convert.ToByte (Int64 Wert)   [0x00000] bei Test.Main   (System.String [] args) [0x00019] in   /home/marco/develop/test/Exceptions.cs:15

Die beste Erklärung, die ich gesehen habe, kann unten gesehen werden, durch einen Link zur Quelle folgt:

“... Die Wahrheit ist etwas komplexer als das. .NET bietet drei Methoden, um von Punkt A nach Punkt B erhalten, wie es war.

Erstens gibt es die implizite Umwandlung. Dies ist die Besetzung, die nicht benötigen Sie etwas mehr als eine Zuordnung zu tun:

int i = 5;
double d = i;

Diese werden auch als „Erweiterungskonvertierungen“ genannt und .NET ermöglicht es Ihnen, führen sie ohne Cast-Operator, weil man nie verlieren Informationen es zu tun: den möglichen Bereich der gültigen Werte eines Doppel umfasst den Bereich der gültigen Werte für ein int und dann einige, so Sie gehen nie diese Aufgabe zu tun und zu entdecken dann zu Ihrem Entsetzen, dass die Laufzeit ein paar Ziffern von Ihrem int Wert gesunken. Zum Referenztypen, die Regel hinter einer impliziten Besetzung ist, dass die Besetzung konnte nie eine InvalidCastException werfen: es an den Compiler klar dass die Besetzung ist immer gültig.

Sie können neue impliziten Cast-Operatoren für eigene Typen machen (was bedeutet, dass Sie implizite Abgüsse, die alle Regeln brechen machen können, wenn Sie sind dumm darüber). Die Faustregel ist, dass ein implizites Guss können, gehören nie die Möglichkeit, Informationen in die zu verlieren Übergang.

Beachten Sie, dass die zugrunde liegende Darstellung haben Änderung in dieser Umwandlung: a. Doppel ganz anders aus einem int dargestellt wird

Die zweite Art der Umwandlung ist eine explizite Umwandlung. Eine explizite Besetzung ist erforderlich überall dort, wo es die Möglichkeit, Informationen zu verlieren, oder gibt es eine Möglichkeit, dass die Besetzung nicht gültig sein könnte und somit werfen ein InvalidCastException:

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

Hier werden Sie natürlich Informationen verlieren: i 1 nach dem sein gegossen, so wird die 0,5 verloren. Dies wird auch als „Verengung“ bekannt Konvertierung und der Compiler erfordert, dass Sie eine explizite Umwandlung umfassen (Int), um anzuzeigen, dass ja, Sie wissen, dass Informationen können verloren gehen, aber Sie kümmern sich nicht.

In ähnlicher Weise mit Referenztypen der Compiler erfordert explizite Casts in Situationen, in denen die Schauspieler während der Laufzeit nicht gültig sein können, als ein Signal dass ja, wissen Sie, es ist ein Risiko, aber Sie wissen, was Sie tun.

Die dritte Art der Umwandlung ist eine, die eine solche radikale Veränderung beinhaltet in Darstellung, dass die Designer bieten nicht einmal eine explizite Stimmen: sie machen Sie eine Methode aufrufen, um die Konvertierung zu tun:

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

Beachten Sie, dass es nichts gibt, das absolut hier einen Methodenaufruf erfordert. Implizite und explizite Casts sind Verfahren auch nennt (das ist, wie Sie machen dein eigenes). Die Designer können ganz einfach ein explizites erstellt haben Cast-Operator, die eine Zeichenfolge auf ein int umgewandelt. Die Forderung, dass Sie rufen eine Methode, eine stilistische Wahl ist eher als ein Grund Anforderung der Sprache.

Die stilistische Argumentation geht ungefähr so: String-to-int a komplizierte Umwandlung mit viel Gelegenheit für Dinge gehen schrecklich falsch:

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

Als solche der Methodenaufruf gibt Ihnen Dokumentation zu lesen, und eine breite andeuten, dass dies etwas mehr als nur eine schnelle gegossen wird.

Wenn Sie Ihre eigenen Arten der Gestaltung (insbesondere Ihre eigenen Wertetypen), Sie kann beschließen, Cast-Operatoren und Konvertierungsfunktionen zu erstellen. Die Linien Dividieren "implicit cast", "explicit cast" und "conversion function" Gebiet ist ein wenig verschwommen, so verschiedene Menschen können unterschiedliche machen Entscheidungen darüber, was sollte, was sein. Versuchen Sie einfach, im Auge zu behalten Informationsverlust und mögliche Ausnahmen und ungültige Daten und dass sollten Sie entscheiden helfen. "

  • Bruce Holz, 16. November 2005

http://bytes.com/forum/post1068532-4.html

Casting beinhaltet Referenzen

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

Beachten Sie, dass Operationen gegen myList, wie das Hinzufügen eines Elements, in myEnumerable und myOtherList reflektiert werden. Dies, weil sie alle Verweise (unterschiedlicher Art) auf dieselbe Instanz sind.

Up-Casting ist sicher. Down-Casting kann Laufzeitfehler erzeugen, wenn der Programmierer einen Fehler in der Art gemacht hat. Sicher unten Guss geht über den Rahmen dieser Antwort.

Umwandlung beinhaltet Instanzen

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

myList verwendet myArray herzustellen. Dies ist eine nicht-destruktive Umwandlung (myList arbeitet völlig in Ordnung, nach dieser Operation). Beachten Sie auch, dass Operationen gegen myList, wie das Hinzufügen eines Elements, die nicht in myArray reflektiert. Dies liegt daran, sie sind völlig separate Instanzen.

decimal w = 1.1m;
int x = (int)w;

Es gibt Operationen die Besetzung Syntax in C #, die tatsächlich Umwandlungen .

Semantics beiseite, ein Schnelltest zeigt sie sind nicht gleich!
Sie haben die Aufgabe, anders (oder vielleicht, sie haben unterschiedliche Aufgaben).

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

Beachten Sie die x=-1.5 und x=1.5 Fälle.

Gegossener der Compiler / interperter ist zu sagen, dass das Objekt in der Tat dieses Typs ist (oder hat einen Basetype / Schnittstelle dieses Typs). Es ist ein ziemlich schnell, was zu tun im Vergleich zu einem Bekehrten, wo es nicht mehr die Compiler / interperter die Arbeit zu tun, aber eine Funktion actualling eine String-Parsing und Mathematik in eine Zahl zu konvertieren tun.

Gießen bedeutet immer den Datentyp eines Objekts zu verändern. Dies kann durch Umwandeln eines Gleitkommawert in einen ganzzahligen Wert beispielsweise durchgeführt werden, oder durch die Bits neu interpretiert. Es ist usally eine Sprachgestützte (sprich: Compiler-unterstützt). Betrieb

Der Begriff „Umwandlung“ wird manchmal zum Gießen verwendet, aber es wird in der Regel durch eine Bibliothek oder Ihren eigenen Code getan und notwendigerweise führt nicht in den gleichen wie Gießen. Zum Beispiel, wenn Sie einen imperiale Gewichtswert haben und es auf metrisches Gewicht zu konvertieren, kann es den gleichen Datentyp (zum Beispiel float) bleiben, aber eine andere Zahl worden. Ein weiteres typisches Beispiel ist von Grad in Radiant umgewandelt wird.

In einem Sprache- / framework unabhängige sozusagen von einem Typ oder eine Klasse in ein anderes umgewandelt wird als bekannt Gießen . Dies gilt für .NET als auch, wie Sie Ihre ersten vier Zeilen zeigen:

object x;
int y;

x = 4;

y = ( int )x;

C und C-ähnliche Sprachen (wie C #) verwenden, um die (newtype)somevar Syntax zum Gießen. In VB.NET, zum Beispiel gibt es explizite integrierte Funktionen für diese. Die letzte Zeile geschrieben werden würde, wie:

y = CInt(x)

Oder für komplexere Typen:

y = CType(x, newtype)

Wo 'C' offensichtlich ist die Abkürzung für 'werfen'.

.NET hat auch die Convert() Funktion jedoch. Dies ist keine eingebauten Sprachmerkmal (im Gegensatz zu den beiden oben genannten), sondern eines der Rahmen. Dies wird deutlicher, wenn man eine Sprache verwenden, die nicht unbedingt zusammen mit .NET verwendet wird. Sie immer noch sehr wahrscheinlich ihre eigenen Mittel des Gießens haben, aber es ist .NET, die Convert() fügt

Wie Matt sagt, ist der Unterschied im Verhalten, dass Convert() deutlicher ist. Anstatt nur zu sagen, die Compiler y als Integer-äquivalent von x zu behandeln, sagen Sie es speziell x so zu verändern, wenn dies für die Integer-Klasse geeignet ist, und weisen Sie das Ergebnis y.

In Ihrem speziellen Fall, wird das Gießen was ‚Unboxing‘ genannt, während Convert() tatsächlich den ganzzahligen Wert erhalten. Das Ergebnis erscheint das gleiche, aber es gibt feine Unterschiede besser erklärt href="https://stackoverflow.com/questions/18465/net-parse-verses-convert#18523">.

Nach Tabelle 1-7 Titel "Verfahren zur Explicit-Konvertierung" auf Seite 55 in Kapitel 1, Lektion 4 von MCTS Paced Training Kit (Prüfung 70-536): Microsoft .NET Framework 2.0-Anwendung Development Foundation , es ist sicherlich ein Unterschied zwischen ihnen.

System.Convert ist sprachunabhängig und Konvertiten "Zwischen-Typen, die die System.IConvertible Schnittstelle . Implementieren"

(Typ) gegossen Operator ist eine C # -spezifische Sprache-Funktion, die konvertiert "Zwischen-Typen, die definieren Konvertierungsoperator ."

Wenn darüber hinaus kundenspezifische Umbauten Implementierung Beratung unterscheidet zwischen ihnen.

Per Abschnitt mit dem Titel Wie Conversion zur Umsetzung in Benutzerdefinierte Typen auf den Seiten. 56-57 in der Lehre wie oben zitiert, Konvertierungsoperator (Gießen) soll für Konvertierungen zwischen numerischen Typen zu vereinfachen, Rechnen Sie während () ermöglicht es kulturspezifische Conversions .

  

Welche Technik Sie wählen, von der Art der Umwandlung ab, die Sie durchführen möchten:

     
      
  • definieren Konvertierungsoperator vereinfachen Verengung und Erweiterung   Umwandlungen zwischen numerischen Typen.

  •   
  • Implement System.IConvertible , um die Umwandlung durch   System.Convert. Verwenden Sie diese Technik kulturspezifischen Umsetzungen zu ermöglichen.

  •   
  • ...

  •   

Es sollte klarer sein, dass jetzt, da der Gussumwandlungsoperator getrennt von der IConvertible Schnittstelle implementiert ist, dass Convert () nicht unbedingt nur ein anderer Name für das Gießen. (Aber ich kann sich vorstellen, wo eine Implementierung auf die andere beziehen Konsistenz zu gewährleisten).

Sie die anderen Methoden des Gießens und Umwandlung Variablen nicht vergessen: wie, Parse, TryParse sowie implizites Casting zwischen kompatibelen Datentypen.

Diese Seite hat eine gute Probe von dem, was die Ausgaben für die meisten Methoden: C # Boxen und Unboxing

So dieses Beispiel Variablen gegeben:

int i = 3, x;
long l;
string s = "5";

Grundsätzlich kann man implizites Casting hat, zwischen zwei kompatibelen Typen:

l = i;

Explicit Gießen Unboxing oder die wie Stichwort:

s = (string)i;
//or
s = i as string;

Explizite Umwandlungen unter Verwendung von Methoden aus System.Convert:

i = System.Convert.ToInt32(s);

Explicit Konvertierungen Verfahren von einem definierten Datentyp:

i = int.Parse(s);
i = int.TryParse(s, x);

Explicit Umwandlungen unter Verwendung von Verfahren aus einer Instanz einer Variablen:

s = i.ToString();

Ich denke Gießen ist einfach eine Möglichkeit, Zuordnungen zwischen zwei kompatibelen Typen zu machen.

Konvertieren , wenn Sie explizit benötigen einen Wert von einem inkompatiblen Typ in einen anderen zu kopieren, und Sie können nicht vertrauen bösen Zwang .

Einige gute Informationen auch auf MSDN: Casting und Typkonvertierungen

Gießen im Wesentlichen sagen, nur die Laufzeit zu „vortäuschen“ das Objekt der neue Typ ist. Es ist nicht wirklich konvertieren oder das Objekt in irgendeiner Weise ändern.

Convert wird jedoch Operationen durchführen eine Art in eine andere drehen.

Als Beispiel:

char caster = '5';
Console.WriteLine((int)caster);

Der Ausgang dieser Aussagen wird 53 sein, denn die ganze Laufzeit ist auf dem Bitmuster aussah und es als int behandeln. Was Sie am Ende immer ist der ASCII-Wert des Zeichens 5, statt der Nummer 5.

Wenn Sie Convert.ToInt32 (Nachlauf) werden Sie jedoch 5 bekommen, weil es tatsächlich die Zeichenfolge liest und modifiziert sie richtig. (Im Grunde weiß er, dass ASCII-Wert 53 ist wirklich der Integer-Wert 5).

Der Unterschied besteht, ob die Konvertierung implizit oder explizit ist. Die erste dort ein gegossenes, ist der zweite ein expliziter Aufruf einer Funktion, die umwandelt. Sie gehen wahrscheinlich über die gleiche Sache auf verschiedene Weise tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top