


Sechs wichtige Konzepte in .NET: Stack, Heap, Werttypen, Referenztypen, Boxing und Unboxing
Einführung
• Übersicht
• Wenn Sie eine Variable hinter „Was“ deklarieren passiert?
•Heap und Stack
•Werttypen und Referenztypen
•Was sind Werttypen und welche Referenztypen?
•Einpacken und Auspacken
•Leistungsprobleme beim Einpacken und Auspacken
1. Übersicht
In diesem Artikel werden sechs wichtige Konzepte erläutert: Heap , Stapel, Werttypen, Referenztypen, Boxing und Unboxing. In diesem Artikel wird zunächst erklärt, was im System passiert, wenn Sie eine Variable definieren, und dann wird der Fokus auf das Speicherduo verlagert: den Heap und den Stack. Später werden wir uns mit Werttypen und Referenztypen befassen und die wichtigen Grundlagen dieser beiden Typen erläutern.
In diesem Artikel wird ein einfacher Code verwendet, um die Auswirkungen auf die Leistung während des Ein- und Auspackvorgangs zu zeigen. Bitte lesen Sie ihn sorgfältig durch.
2. Was passiert hinter den Kulissen, wenn Sie eine Variable deklarieren?
Wenn Sie eine Variable in einer .NET-Anwendung definieren, wird ihr ein Speicherblock im RAM zugewiesen. Dieser Speicher enthält drei Dinge: den Namen der Variablen, den Datentyp der Variablen und den Wert der Variablen.
Das Obige ist eine kurze Erklärung dessen, was im Speicher passiert, aber genau welcher Art von Speicher Ihre Variable zugewiesen wird, hängt vom Datentyp ab. In .NET gibt es zwei Arten von zuweisbarem Speicher: Stack und Heap. In den nächsten Abschnitten werden wir versuchen, diese beiden Speicherarten im Detail zu verstehen.
3. Speicher-Duo: Heap und Stack
Um den Stapel und den Heap zu verstehen, lassen Sie uns anhand des folgenden Codes verstehen, was hinter den Kulissen passiert.
public void Method1() { // Line 1 int i=4; // Line 2 int y=2; //Line 3 class1 cls1 = new class1(); }
Es gibt nur drei Zeilen Code. Jetzt können wir verstehen, wie er intern Zeile für Zeile ausgeführt wird.
•Zeile 1: Wenn diese Zeile ausgeführt wird, weist der Compiler einen kleinen Teil des Speichers auf dem Stapel zu. Der Stack ist dafür verantwortlich, zu verfolgen, ob Ihre Anwendung laufenden Speicher benötigt
•Zeile 2: Der zweite Schritt wird nun ausgeführt. Wie der Name schon sagt, stapelt der Stack hier eine kleine Speicherzuweisung zusätzlich zu der gerade im ersten Schritt vorgenommenen Speicherzuweisung. Sie können sich einen Stapel als übereinander gestapelte Räume oder Kisten vorstellen. Im Stapel werden Daten über die LIFO-Logikregel (Last In First Out) zugewiesen und freigegeben. Mit anderen Worten: Das Datenelement, das zuerst in den Stapel gelangt, kann das letzte sein, das den Stapel verlässt.
•Zeile 3: In der dritten Zeile erstellen wir ein Objekt. Wenn diese Zeile ausgeführt wird, erstellt .NET einen Zeiger auf dem Stapel und das eigentliche Objekt wird in einem Speicherbereich namens „Heap“ gespeichert. Der „Heap“ überwacht den laufenden Speicher nicht, es handelt sich lediglich um eine Ansammlung von Objekten, auf die jederzeit zugegriffen werden kann. Im Gegensatz zum Stack wird der Heap für die dynamische Speicherzuweisung verwendet.
•Ein weiterer wichtiger Punkt, den es hier zu beachten gilt, ist, dass der Referenzzeiger des Objekts auf dem Stapel zugewiesen wird. Beispiel: Die Deklarationsanweisung Class1 cls1 reserviert tatsächlich keinen Speicher für die Instanz von Class1, sondern erstellt lediglich einen Referenzzeiger für die Variable cls1 auf dem Stapel (und setzt ihre Standardposition auf Null). Erst wenn das neue Schlüsselwort gefunden wird, wird Speicher für das Objekt auf dem Heap reserviert.
•Beim Verlassen dieser Methode Methode1 (der Spaß): Jetzt beginnt die Ausführungskontrollanweisung, den Methodenkörper zu verlassen. Zu diesem Zeitpunkt wird der gesamte für Variablen zugewiesene Speicherplatz auf dem Stapel gelöscht. Mit anderen Worten: Im obigen Beispiel werden alle Variablen, die sich auf den Typ int beziehen, einzeln nach dem LIFO-Prinzip „Last-In-First-Out“ aus dem Stapel entfernt.
•Es ist zu beachten, dass die Speicherblöcke im Heap zu diesem Zeitpunkt nicht freigegeben werden. Die Speicherblöcke im Heap werden später vom Garbage Collector bereinigt.
Jetzt sind viele unserer Entwicklerfreunde sicher neugierig, warum es zwei verschiedene Arten von Speicher gibt? Warum können wir nicht alle Speicherblöcke nur einem Speichertyp zuordnen?
Wenn Sie genau hinsehen, sind primitive Datentypen nicht komplex, sie enthalten lediglich Werte wie „int i = 0“. Objektdatentypen sind komplizierter; sie verweisen auf andere Objekte oder andere primitive Datentypen. Mit anderen Worten: Sie enthalten Verweise auf mehrere andere Werte und diese Werte müssen einzeln im Speicher gespeichert werden. Objekttypen erfordern dynamischen Speicher, während primitive Typen statischen Speicher erfordern. Wenn dynamischer Speicher benötigt wird, wird Speicher dafür auf dem Heap zugewiesen, andernfalls wird er auf dem Stapel zugewiesen.
4. Werttypen und Referenztypen
Da wir nun die Konzepte von Stack und Heap verstanden haben, ist es an der Zeit, Werttypen zu verstehen und Referenzen Das Konzept des Typs. Werttypen halten sowohl Daten als auch Speicher am selben Ort, während ein Referenztyp einen Zeiger auf den tatsächlichen Speicherbereich hat.
In der folgenden Abbildung sehen wir einen ganzzahligen Datentyp namens i, dessen Wert einem anderen ganzzahligen Datentyp namens j zugewiesen ist. Ihre Werte werden auf dem Stapel gespeichert.
Wenn wir einen Wert vom Typ int einem anderen Wert vom Typ int zuweisen, wird tatsächlich eine völlig andere Kopie erstellt. Mit anderen Worten: Wenn Sie den Wert des einen ändern, ändert sich der andere nicht. Daher werden solche Datentypen „Werttypen“ genannt.
Wenn wir ein Objekt erstellen und dieses Objekt einem anderen Objekt zuweisen, verweisen beide auf denselben Speicherbereich, wie im folgenden Codeausschnitt gezeigt. Wenn wir also obj obj1 zuweisen, verweisen beide auf denselben Bereich im Heap. Mit anderen Worten: Wenn wir einen von ihnen zu diesem Zeitpunkt ändern, ist der andere davon betroffen, was auch erklärt, warum sie „Referenztypen“ genannt werden.
5. Welche sind Werttypen und welche sind Referenztypen?
In .NET hängt es vollständig vom Datentyp ab, zu dem sie gehört, ob eine Variable auf dem Stapel oder im Heap gespeichert wird. Beispiel: „String“ oder „Object“ sind Referenztypen, während andere primitive .NET-Datentypen auf dem Stapel zugewiesen werden. Die folgende Abbildung zeigt im Detail, welche der .NET-Voreinstellungstypen Werttypen und welche Referenztypen sind.
6. Einpacken und Auspacken
Jetzt haben Sie bereits viele theoretische Grundlagen. Jetzt ist es an der Zeit zu verstehen, wie das oben genannte Wissen in der tatsächlichen Programmierung genutzt wird. Eine der größten Auswirkungen bei Anwendungen besteht darin, die Leistungsverbrauchsprobleme zu verstehen, die auftreten, wenn Daten vom Stapel auf den Heap verschoben werden und umgekehrt.
Betrachten Sie den folgenden Codeausschnitt. Wenn wir einen Werttyp in einen Referenztyp konvertieren, werden die Daten vom Stapel auf den Heap verschoben. Wenn wir umgekehrt einen Referenztyp in einen Werttyp konvertieren, werden die Daten auch vom Heap auf den Stapel verschoben.
Ob es vom Stapel zum Heap oder vom Heap zum Stapel verschoben wird, es wird unweigerlich einen gewissen Einfluss auf die Systemleistung haben.
Als Ergebnis entstanden zwei neue Begriffe: Wenn die Daten von einem Werttyp in einen Referenztyp konvertiert werden, wird der Vorgang als „Boxen“ bezeichnet, und der Prozess der Konvertierung von einem Referenztyp in Ein Werttyp heißt „Boxing“.
Wenn Sie den obigen Code kompilieren und ihn in ILDASM (einem IL-Dekompilierungstool) anzeigen, werden Sie im IL-Code feststellen, wie das Ein- und Auspacken aussieht wie. Die folgende Abbildung zeigt den IL-Code, der nach der Kompilierung des Beispielcodes generiert wird.
7. Leistungsprobleme beim Ein- und Auspacken
Um es herauszufinden Welche Auswirkungen haben das Ein- und Auspacken auf die Leistung? Wir führen die beiden in der Abbildung unten gezeigten Funktionsmethoden 10.000 Mal in einer Schleife aus. Die erste Methode verfügt über Boxoperationen, die andere nicht. Wir verwenden ein Stopwatch-Objekt, um den Zeitverbrauch zu überwachen.
Die Methode mit Boxing-Operation dauerte 3542 Millisekunden, während die Methode ohne Boxing-Operation nur 2477 Millisekunden dauerte, was einem Unterschied von mehr als 1 Sekunde entspricht. Darüber hinaus erhöht sich auch dieser Wert mit zunehmender Zyklenzahl. Mit anderen Worten: Wir sollten versuchen, Ein- und Auspackvorgänge zu vermeiden. Wenn Sie in einem Projekt „Boxen und Boxen“ benötigen, überlegen Sie sorgfältig, ob es sich um einen unbedingt notwendigen Vorgang handelt. Wenn nicht, versuchen Sie, ihn nicht zu verwenden.
Obwohl der obige Codeausschnitt Zeigt das Unboxing nicht an, aber der Effekt gilt auch für das Unboxing. Sie können das Unboxing implementieren, indem Sie Code schreiben und seinen Zeitverbrauch mit Stopwatch testen.
Die oben genannten sechs wichtigen Konzepte in .NET: Stack, Heap, Werttyp, Referenztyp, Boxing und Unboxing. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn). )!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Die Nutzungsmethoden von Symbolen in der C-Sprachabdeckung Arithmetik, Zuordnung, Bedingungen, Logik, Bitoperatoren usw. werden für grundlegende mathematische Operationen verwendet, Zuordnungsoperatoren werden zur Zuordnung und Addition verwendet, Subtraktion, Multiplikationszuordnung und Abteilungszuweisung, Zustandsbetreiber werden für Unterschiede verwendet. Logische Operationen werden verwendet. Logische Operationen werden verwendet. Logische Operationen werden verwendet. Zeiger, Markierungen am Ende der Datei und nicht numerische Werte.

Der Unterschied zwischen Multithreading und Asynchron besteht darin, dass Multithreading gleichzeitig mehrere Threads ausführt, während asynchron Operationen ausführt, ohne den aktuellen Thread zu blockieren. Multithreading wird für rechenintensive Aufgaben verwendet, während asynchron für die Benutzerinteraktion verwendet wird. Der Vorteil des Multi-Threading besteht darin, die Rechenleistung zu verbessern, während der Vorteil von Asynchron nicht darin besteht, UI-Threads zu blockieren. Die Auswahl von Multithreading oder Asynchron ist von der Art der Aufgabe abhängt: Berechnungsintensive Aufgaben verwenden Multithreading, Aufgaben, die mit externen Ressourcen interagieren und die UI-Reaktionsfähigkeit asynchron verwenden müssen.

Das Char -Array speichert Zeichensequenzen in der C -Sprache und wird als char Array_name [Größe] deklariert. Das Zugriffselement wird durch den Einweisoperator weitergeleitet, und das Element endet mit dem Null -Terminator '\ 0', der den Endpunkt der Zeichenfolge darstellt. Die C -Sprache bietet eine Vielzahl von String -Manipulationsfunktionen wie Strlen (), Strcpy (), Strcat () und strcmp ().

In C wird der Zeichenentyp in Saiten verwendet: 1. Speichern Sie ein einzelnes Zeichen; 2. Verwenden Sie ein Array, um eine Zeichenfolge darzustellen und mit einem Null -Terminator zu enden. 3. Durch eine Saitenbetriebsfunktion arbeiten; 4. Lesen oder geben Sie eine Zeichenfolge von der Tastatur aus.

In der C -Sprache werden Sonderzeichen durch Escape -Sequenzen verarbeitet, wie z. B.: \ n repräsentiert Linienbrüche. \ t bedeutet tab charakter. Verwenden Sie Escape -Sequenzen oder Zeichenkonstanten, um Sonderzeichen darzustellen, wie z. B. char c = '\ n'. Beachten Sie, dass der Backslash zweimal entkommen muss. Verschiedene Plattformen und Compiler haben möglicherweise unterschiedliche Fluchtsequenzen. Bitte wenden Sie sich an die Dokumentation.

In der C -Sprache kann die char -Typ -Konvertierung direkt in einen anderen Typ konvertiert werden, wenn: Casting: Verwenden von Casting -Zeichen. Automatische Konvertierung des Typs: Wenn ein Datentyp einen anderen Werttyp berücksichtigen kann, wandelt der Compiler diese automatisch um.

Es gibt keine integrierte Summenfunktion in der C-Sprache, daher muss sie selbst geschrieben werden. Die Summe kann erreicht werden, indem das Array durchquert und Elemente akkumulieren: Schleifenversion: Die Summe wird für die Schleifen- und Arraylänge berechnet. Zeigerversion: Verwenden Sie Zeiger, um auf Array-Elemente zu verweisen, und eine effiziente Summierung wird durch Selbststillstandszeiger erzielt. Dynamisch Array -Array -Version zuweisen: Zuordnen Sie Arrays dynamisch und verwalten Sie selbst den Speicher selbst, um sicherzustellen, dass der zugewiesene Speicher befreit wird, um Speicherlecks zu verhindern.

In der C -Sprache ist der Hauptunterschied zwischen char und wchar_t die Zeichencodierung: char verwendet ASCII oder erweitert ASCII, wchar_t Unicode; char nimmt 1-2 Bytes auf, wchar_t nimmt 2-4 Bytes auf; char ist für englischen Text geeignet. Wchar_t ist für mehrsprachige Text geeignet. char ist weithin unterstützt, wchar_t hängt davon ab, ob der Compiler und das Betriebssystem Unicode unterstützen. char ist in der Charakterbereich begrenzt, WCHAR_T hat einen größeren Charakterbereich und spezielle Funktionen werden für arithmetische Operationen verwendet.
