Was ist der Unterschied zwischen Boxen / Unboxen und Typ Casting?


73

Was ist der Unterschied zwischen Boxen / Unboxen und Typ Casting?

Oft scheinen die Begriffe synonym verwendet zu werden.


1
Ich musste die beiden Top-2-Antworten hier lesen, um eine gute Vorstellung davon zu bekommen, was der Unterschied ist, aber ich denke, ich habe jetzt einen ziemlich festen Überblick
Code Jockey

Antworten:


47

Boxing bezieht sich auf eine Konvertierung eines nicht nullbaren Werttyps in einen Referenztyp oder auf die Konvertierung eines Werttyps in eine von ihm implementierte Schnittstelle (z. B. intzu IComparable<int>). Ferner ist die Umwandlung eines zugrunde liegenden Werttyps in einen nullbaren Typ auch eine Boxumwandlung. (Vorsichtsmaßnahme: Bei den meisten Diskussionen zu diesem Thema werden die beiden letztgenannten Arten von Konvertierungen ignoriert.)

Zum Beispiel,

int i = 5;
object o = i;

Konvertiert iin eine Instanz vom Typ object.

Unboxing bezieht sich auf eine explizite Konvertierung von einer Instanz eines objectoder ValueTypeeines nicht nullbaren Werttyps, die Konvertierung eines Schnittstellentyps in einen nicht nullbaren Werttyp (z . B. IComparable<int>in int). Ferner ist die Konvertierung eines nullbaren Typs in den zugrunde liegenden Typ auch eine Unboxing-Konvertierung. (Vorsichtsmaßnahme: Bei den meisten Diskussionen zu diesem Thema werden die beiden letztgenannten Arten von Konvertierungen ignoriert.)

Zum Beispiel,

object o = (int)5;
int i = (int)o;

konvertiert die Ganzzahl in oeine Instanz vom Typ int.

Eine Typumwandlung ist eine explizite Konvertierung eines Ausdrucks in einen bestimmten Typ. So

(type) expression

Konvertiert explizit expressionin ein Objekt vom Typ type.


Vielen Dank. Es scheint keine Standardsprache für diese Dinge zu geben.

11
Es gibt eine sehr Standardsprache in Bezug auf diese Dinge. Siehe die C # -Sprachspezifikation, ECMA # 334.
Jason

15
Wenn Jason der Klarheit halber sagt, dass "die Konvertierung eines zugrunde liegenden Werttyps in einen nullbaren Typ auch eine Box-Konvertierung ist", bedeutet er mit "nullfähiger Typ" einen Referenztyp, der auf null gesetzt werden kann - daher seine Verwendung des Begriff "nullable". Was er NICHT meint, ist der Nullable<T>Typ. Das Umwandeln eines Werttyps in einen Nullable<T>(aka T?) ist KEIN Beispiel für Boxing / Unboxing, da kein Referenztyp erstellt wird. Zum Beispiel int? x = 5ist ein Beispiel für eine Typbesetzung, NICHT Boxen.
Drwatsoncode

1
"Zum Beispiel ist int? X = 5 ein Beispiel für eine Typbesetzung, NICHT Boxen." Der Vollständigkeit halber ist es ein Beispiel für eine Besetzung vom Typ IMPLICIT, im Gegensatz zu dem expliziten Beispiel für die Besetzung von Jason.
Almulo

Wenn du wirken kannst, ist es dann möglich, die Übertragung aufzuheben? dh wird der Speicher auf dem Heap freigegeben?
BKSpurgeon

29

Boxen und Unboxen ist eine Teilmenge der Typbesetzungen. Beim Boxen wird ein Werttyp als Referenztyp behandelt (in der Praxis wird der Inhalt dieses Werttyps (vom Stapel) auf den Heap kopiert und eine Referenz auf dieses Objekt zurückgegeben). Dadurch kann ein Werttyp überall dort übergeben werden, wo ein kompatibler Referenztyp erwartet wird. Außerdem können virtuelle Methodenaufrufe und andere Funktionen von Referenztypen für den Werttyp ausgeführt werden. Das Unboxing ist die Umkehrung dieses Vorgangs (Zurückholen eines Werttyps aus einem Boxed-Objekt).

Typumwandlung ist der Begriff, der für jede Art der Konvertierung von einer Variablen eines bestimmten Typs in eine andere verwendet wird. Es ist ein umfassenderes Konzept.

Vor einigen Minuten habe ich eine verwandte Frage beantwortet, die diesen Unterschied abdeckt . Zusammenfassend habe ich verschiedene Arten von IL-Anweisungen kategorisiert, die vom C # Cast-Operator generiert wurden:

  1. Boxen ( boxIL-Anweisung) und Unboxing ( unboxIL-Anweisung)
  2. Casting durch die Vererbungshierarchie (wie dynamic_cast<Type>in C ++, verwendet castclassIL-Anweisung zur Überprüfung)
  3. Casting zwischen primitiven Typen (wie static_cast<Type>in C ++ gibt es viele IL-Anweisungen für verschiedene Arten von Casts zwischen primitiven Typen)
  4. Aufrufen von benutzerdefinierten Konvertierungsoperatoren (auf IL-Ebene handelt es sich lediglich um Methodenaufrufe an die entsprechende op_XXXMethode).

3
Das hilft mir nicht sehr. Ich denke, ich werde im Internet recherchieren, um spezifische Definitionen zum Vergleichen zu finden.

1
Ich würde nicht sagen, dass Boxen / Unboxen überhaupt eine Teilmenge des Castings sind. Es geht darum, Werttypen in Referenztypen zu verschieben, damit sie an anderer Stelle geändert / gespeichert werden können. Beim Casting wird ein Referenztyp erneut unterbrochen.
Simeon Pilgrim

@Simeon: Aus Sicht des Sprachdesigns ist ein Boxed Int nur ein anderer Typ, und Sie konvertieren zwischen verschiedenen Typen.
Mehrdad Afshari

Wobei a es als denselben Typ betrachten würde (beide sind zum Beispiel int's), aber unterschiedliche Arten, ein int zu speichern. Aber von einem C-Hintergrund aus ist es nur ein Hinweis auf mich.
Simeon Pilgrim

@Simeon: Es ist die falsche Art, über Boxen nachzudenken. Wahrscheinlich ein direktes Artefakt des Denkens über die Unterscheidung zwischen Stapel und Haufen. Wie gesagt, semantisch wird nur ein Werttyp in einen Typ mit Referenzmerkmalen konvertiert. Beachten Sie, dass es im Gegensatz int*dazu immer noch unveränderlich ist. Und es sind nicht wirklich nur 4 Bytes auf dem Heap. Es enthält Typinformationen und ruft virtuelle Methoden auf: object o = 5; string s = o.ToString();funktioniert aus diesem Grund. Dies ist unmöglich mit einem einfachen zu tun int*. In C ++ beinhaltet dies vtables, ... und das Boxen muss auch mit diesem Zeug umgehen.
Mehrdad Afshari

20

Boxen ist der Begriff für die Umwandlung eines Werttyps (int, double, float, Guid usw.) in einen Referenztyp (System.Object, System.String usw.). Durch diese Boxoperation wird Speicher auf dem Heap zugewiesen (den der Garbage Collector eventuell zurückfordern muss). Das Unboxing ist die Umkehrung dieses Prozesses, bei dem ein Referenztyp in einen Werttyp umgewandelt wird.

Beim Casting wird ein Typ (z. B. System.Object) als ein anderer Typ (z. B. System.String) behandelt.

Wenn Sie etwas in C # boxen, wandeln Sie es in einen anderen Typ um. Der Unterschied besteht darin, dass beim Erstellen eines neuen Referenztyps zusätzlicher Speicher zugewiesen wird .

Fazit: Boxen ist eine spezielle Art der Besetzung, bei der ein Werttyp in einen Referenztyp konvertiert wird, für den ein neuer Referenztyp zugewiesen werden muss.


2
Heap ist ein Implementierungsdetail.
Jason

1
Dieses "Haufen" -Detail hilft mir tatsächlich, es besser zu verstehen!

5
Nicht ganz richtig. Zunächst ist es nicht unbedingt System.Object, sondern ein beliebiger Referenztyp . Zum Beispiel IComparable<int> i = 5führt auch das Boxen. Zweitens boxingist dies nicht die einzige Besetzung, die eine Speicherzuweisung erfordert. Benutzerdefinierte Casts können dies ebenfalls tun. Drittens, wie Jason betonte, ist Heap das Implementierungsdetail. Das Wichtigste ist , einen Werttyp nach Referenztypsemantik zu behandeln, nicht dort, wo er zugeordnet ist.
Mehrdad Afshari

1
Es gibt Zeiten, in denen ich Programmierer für übermäßig pedantisch halte. Dies ist eine dieser Zeiten.
Judah Gabriel Himango

2
Müssen wir ehrlich in eine Debatte darüber geraten, dass der Haufen ein Implementierungsdetail ist, als das Poster einfach nach dem Unterschied zwischen Casting und Boxen fragte? Meine Antwort war richtig - die CLR reserviert Speicher auf dem Heap für das Boxen. Sie weisen korrekt, wenn auch pedantisch, darauf hin, dass der Heap ein Implementierungsdetail ist. Ich kann erwidern: "Aber es ist die aktuelle Implementierung, eine bemerkenswerte, und es ist unwahrscheinlich, dass sie sich in absehbarer Zukunft ändert." --- EHRLICH --- Wir entwickeln uns mit dieser Art von pedantischem Geplänkel in Albernheit.
Judah Gabriel Himango

4

Boxing / Unboxing und Type Casting sind zwei verschiedene Operationen, sie verwenden jedoch dieselbe Syntax.

Sie werden nur synonym verwendet, wenn die Person, die darüber spricht, nicht weiß, was wirklich passiert ...

Beim Boxen wird ein Werttyp als Objekt auf dem Heap gespeichert, und beim Unboxing wird der Wert aus dem Objekt gelesen. Sie können den Wert nur als genauen Typ entpacken.

Casting ist, wenn Sie einen Basistyp in einen anderen Basistyp konvertieren (wie von a intnach a long) oder wenn Sie den Typ einer Referenz ändern (wie von List<int>nach IEnumerable<int>).


1
Ich weiß das Ich frage, was die Unterschiede sind!

1
Vielen Dank! Das habe ich gesucht!

3

Boxen bedeutet, eine Werttypvariable (dh eine Ganzzahl) in einen Referenztyp umzuwandeln. Unboxing ist das Gegenteil davon, wenn Sie Typ Casting verwenden. In der .NET-Welt leitet sich alles vom Typ "Objekt" ab.

Zum Beispiel (C # Beispiel):

int myInt = 0;                 // original variable (unboxed to begin with)
object boxed = myInt;          // box it up
int myIntUnBoxed = (int)boxed; // and unbox it again using type casting

Dies hat zur Folge, dass das Typensystem vereinheitlicht wird und Werttypen als Referenztypen behandelt werden können. Dieser Artikel befasst sich eingehender mit Boxen / Unboxen.


Hat die Basissprache nicht immer zugelassen, dass Wert- / Referenztypen gleich behandelt werden? Ist das eine C # -spezifische Sache?

Man könnte sagen, dass die Idee des Boxens / Unboxing aus der Basissprache (also vor VB.NET) stammt. Es ist nicht auf C # beschränkt, da dieselben Konzepte auf VB.NET oder jede andere Sprache angewendet werden können, die auf die .NET-Laufzeit abzielt. Es ist lange her, dass ich in der Basissprache codiert habe ... ah die Erinnerungen.
Ajawad987
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.