Heim  >  Artikel  >  Backend-Entwicklung  >  Beispiel-Tutorial zum Ein- und Auspacken

Beispiel-Tutorial zum Ein- und Auspacken

零下一度
零下一度Original
2017-06-23 15:13:061613Durchsuche
Boxing:
Werttypen sind „leichter“ als Referenztypen, da sie nicht als Objekte im verwalteten Heap zugewiesen werden, nicht durch Garbage Collection erfasst werden und nicht durch Zeiger referenziert werden. Oft ist es jedoch erforderlich, einen Verweis auf einen Werttyp zu erhalten. Angenommen, Sie möchten ein ArrayList-Objekt erstellen, um eine Reihe von Punktstrukturen zu speichern. Der Code lautet wie folgt:
öffentliches versiegeltes Klassenprogramm
{
public static void Main()
{
ArrayList a = new ArrayList();
Point p; /Einen Punkt zuweisen (nicht im Heap zugewiesen)
for (int i = 0; i < 10; i++)
{
p.x = p.y = i; //Elemente im Werttyp initialisieren
a.Add(p); //Boxen Sie den Werttyp ein und fügen Sie den Verweis zur ArrayList hinzu
}
}
}
Jede Schleifeniteration initialisiert ein Feld vom Typ Ponit-Wert und speichert den Punkt in einer ArrayList. Aber überlegen Sie, was genau in ArrayList gespeichert ist? Handelt es sich um eine Point-Struktur, die Adresse einer Point-Struktur oder um etwas ganz anderes? Um die richtige Antwort zu erfahren, müssen Sie die Add-Methode von ArrayList untersuchen, um zu verstehen, als welchen Typ ihre Parameter definiert sind. Der Prototyp der Add-Methode in diesem Beispiel lautet wie folgt:
public virtual int Add (Object value); Durch Hinzufügen wird das Objekt auf dem verwalteten Heap abgerufen. Ein Verweis auf ein Objekt als Parameter. Aber der vorherige Code hat p übergeben, was ein Punkt ist, der ein Werttyp ist. Damit der Code ordnungsgemäß funktioniert, muss der Werttyp „Point“ in ein reales Objekt konvertiert werden, das auf dem Heap gehostet wird, und es muss ein Verweis auf das Objekt abgerufen werden.
Konvertieren Sie Werttypen mithilfe des Boxing-Mechanismus in Referenztypen. Folgendes passiert, wenn Sie eine Instanz eines Werttyps einpacken:
1. Reservieren Sie Speicher im verwalteten Heap. Die zugewiesene Speichermenge ist die Speichermenge, die für jedes Feld des Werttyps erforderlich ist, plus die Speichermenge, die für die beiden zusätzlichen Mitglieder (Typobjektzeiger und Synchronisationsblockindex) erforderlich ist, über die alle Objekte im verwalteten Heap verfügen
2. Das Werttypfeld wird in den neu zugewiesenen Heap-Speicher kopiert
3 und die Objektadresse wird zurückgegeben. Jetzt ist das Objekt eine Objektreferenz; der Werttyp wird zu einem Referenztyp
Der C#-Compiler erkennt, dass der obige Code einen Werttyp an eine Methode übergibt, die einen Referenztyp erfordert, und generiert daher automatisch Code für die Box das Objekt. Zur Laufzeit werden also die aktuell in der Point-Werttypinstanz p vorhandenen Felder in das neu zugewiesene Point-Objekt kopiert. Die Adresse des eingerahmten Point-Objekts (jetzt ein Referenztyp) wird zurückgegeben und an die Add-Methode übergeben. Punktobjekte bleiben im Heap, bis sie durch den Müll gesammelt werden. Die Punktwerttypvariable p kann wiederverwendet werden, da ArrayList nichts darüber weiß. In diesem Fall übersteigt die Lebensdauer des Boxed-Typs die Lebensdauer des Boxed-Value-Typs.
Unboxing:
Angenommen, Sie möchten den folgenden Code verwenden, um das erste Element von ArrayList abzurufen:
Punkt p=(Punkt)a[ 0] ;
Er erhält die Referenz, die in Element 0 der ArrayList enthalten ist, und die Ansicht fügt sie in die Instanz p des Point-Werttyps ein. Dazu müssen alle Felder im Boxed Point-Objekt in Variablen vom Typ Wert kopiert werden, die sich auf dem Thread-Stack befinden. Die CLR führt den Kopiervorgang in zwei Schritten durch. Der erste Schritt besteht darin, die Adresse jedes Punktfelds im eingerahmten Punktobjekt abzurufen. Dieser Vorgang wird als Unboxing bezeichnet. Der zweite Teil kopiert den im Feld enthaltenen Wert vom Heap in die stapelbasierte Werttypinstanz
Unboxing kehrt den Boxing-Prozess nicht direkt um. Unboxing ist viel weniger Code als Boxing. Beim Unboxing handelt es sich im Wesentlichen um den Prozess, einen Zeiger auf einen primitiven Werttyp zu erhalten, der in einem Objekt enthalten ist. Tatsächlich zeigt der Zeiger auf den nicht geschachtelten Teil der geschachtelten Instanz. Daher erfordert Chaxiang im Gegensatz zum Boxen kein Kopieren von Bytes in den Speicher. Nachdem Sie diesen wichtigen Unterschied kennen, ist es ein weiterer wichtiger Punkt, dass darauf häufig eine Feldkopie folgt.
Wenn eine Boxed-Value-Typ-Instanz entpackt wird, passieren intern die folgenden Dinge:
1. Wenn die Variable, die „einen Verweis auf den Boxed-Value-Typ“ enthält, null ist, wird eine NullReferenceException
ausgelöst
2, wenn das referenzierte Objekt keine Box-Instanz des erforderlichen Werttyps ist, werfen Sie InvalidCastException
Der zweite Punkt bedeutet, dass die Arbeit des Codes sich von der Methode unterscheiden kann Sie denken:
public static void Main()
{
Int32 x = 5;
Object o = x; //Box x, o bezieht sich auf das Boxed-Objekt
Int16 y = (Int16)o; //Throws InvalidCastException
}
Logisch gesehen ist es durchaus möglich, das Boxed Int32 zu erhalten, auf das verwiesen wird o und erzwingen die Konvertierung in int16. Beim Entpacken des Objekts kann es jedoch nur in den ursprünglichen entpackten Werttyp konvertiert werden – in diesem Fall Int32. Die folgende Schreibweise lautet:
public static void Main()
{
Int32 x = 5;
Object o = x; //boxing x, o reference has been Boxed object
Int16 y = (Int16)(Int32)o; //Entpacken Sie es zuerst in den richtigen Typ und transformieren Sie es dann
}
Sehen Sie sich den folgenden Code an:
public static void Main()
{
Point p;
p.x = p.y = 1;
Object o = p //Box p; , o bezieht sich auf die Box-Instanz
//Ändern Sie das x-Feld von Point auf 2
p = (Point)o; //Entpacken Sie o und kopieren Sie die Felder aus der Box-Instanz in die Stapelvariable
p.x = 2; //Ändern Sie den Status der Stapelvariablen
o = p; //Box p, o bezieht sich auf die neue Box-Instanz
}
Der einzige Zweck der letzten drei Codezeilen besteht darin, das x-Feld von Point von 1 zu ändern Wird 2. Führen Sie dazu zunächst ein Unboxing durch, führen Sie dann eine Feldkopie durch, ändern Sie dann das Feld (auf dem Stapel) und führen Sie schließlich ein Boxing durch (erstellen Sie eine brandneue Box-Instanz auf dem verwalteten Heap). Dies zeigt die Auswirkungen des Ein- und Auspackens auf die Anwendungsleistung.
Fragen:
public static void Main()
{
Int32 v = 5;
Object o = v;
v = 123;
Console.WriteLine(v+","+(Int32)o);
}
Wie oft wurde der obige Code ausgeführt? auftreten?

Das obige ist der detaillierte Inhalt vonBeispiel-Tutorial zum Ein- und Auspacken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn