Frage

Ist es möglich, in C # eine Struktur mit einer Membervariable zu haben, die ein Klasse-Typ ist? Wenn ja, wo kommt die Informationen gespeichert sind, auf dem Stapel, der Haufen, oder beides?

War es hilfreich?

Lösung

Ja, Sie können. Der Zeiger auf die Klassenvariable gespeichert auf dem Stapel mit dem Rest der Werte der Struktur, und die Daten des Klasseninstanz wird auf dem Heap gespeichert.

Structs können auch enthalten Klassendefinitionen als Mitglieder (innere Klassen).

Hier ist ein wirklich nutzlos Code, der am wenigsten compiliert bei und zeigen läuft, dass es möglich:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStr m = new MyStr();
            m.Foo();

            MyStr.MyStrInner mi = new MyStr.MyStrInner();
            mi.Bar();

            Console.ReadLine();
        }
    }

    public class Myclass
    {
        public int a;
    }

    struct MyStr
    {
        Myclass mc;

        public void Foo()
        {
            mc = new Myclass();
            mc.a = 1;
        }

        public class MyStrInner
        {
            string x = "abc";

            public string Bar()
            {
                return x;
            }
        }
    }
}

Andere Tipps

Der Klasseninhalt auf dem Heap gespeichert wird.

Ein Verweis auf die Klasse (die fast das gleiche wie ein Zeiger ist) wird mit der Struktur Inhalt gespeichert. Wo die Struktur Inhalt gespeichert wird, hängt davon ab, ob es eine lokale Variable, Methodenparameter oder Mitglied einer Klasse, und ob er durch einen Verschluss verpackt oder gefangen genommen worden ist.

Wenn eines der Felder einer Struktur ein Klassentyp ist, wird dieses Feld entweder halten Sie die Identität von einem Klassenobjekt oder auch einen Null-referece. Wenn die Klasse in Frage stehenden Objekt unveränderlich ist (zum Beispiel string), wird seine Identität zu speichern effektiv speichert auch ihren Inhalt handeln. Wenn die Klasse Objekt in Frage wandelbar ist, wird jedoch die Identität Speicherung seines ein wirksames Mittel zur Speicherung des Inhalts , wenn und nur wenn die Referenz wird nicht in die Hände von Code fallen, die sie mutieren könnten, sobald es gespeichert ist, in das Feld .

Generell sollte man wandelbar Klassentypen innerhalb einer Struktur zu speichern vermeiden, es sei denn eine von zwei Situationen zutrifft:

  1. Was man interessiert ist, in der Tat, die Identität des Klassenobjekts statt dessen Inhalt. Zum Beispiel könnte man eine `FormerControlBounds` Struktur definieren, welche Felder vom Typ hält` Control` und `Rectangle` und stellt die` Bounds`, die zu einem bestimmten Zeitpunkt hatte die Kontrolle, für die Zwecke der Lage zu später die Kontrolle wiederherzustellen in seine frühere Position. Der Zweck des `Control` Feldes würde nicht eine Kopie der Kontrolle des Staates zu halten sein, sondern um die Kontrolle, deren Position zu identifizieren, soll gestellt werden. Im Allgemeinen sollte die Struktur vermeiden alle wandelbar Mitglieder des Objekts zugreifen, auf die sie einen Verweis hält, außer in Fällen, in denen klar ist, dass ein solcher Zugriff auf den aktuellen wandelbaren Zustand des Objekts in Frage bezieht (zB in einem `CaptureControlPosition` oder` RestoreControlToCapturedPosition` Methode oder eine `ControlHasMoved` Eigenschaft).
  2. Das Feld ist `private`, die einzigen Methoden, die es für den Zweck so lesen tun, um seine Eigenschaften zu untersuchen, ohne Aussetzen des Objekts selbst es außerhalb Code, und die einzigen Methoden, die sie schreiben, wird eine neue erstellen Objekt, führen alle der Mutationen, die jemals es geschehen werden, und speichern sie dann einen Verweis auf das Objekt. Man könnte zum Beispiel der Gestaltung eines `struct`, die viel wie ein Array verhalten hat, aber mit dem Wert Semantik, indem die Struktur ein Array in einem privaten Bereich hält, und durch jeden Versuch, mit zu schreiben, erstellen das Array ein neues Array mit Daten von der alten, modifizieren, die neue Anordnung, und speichern die modifizierte Anordnung in diesem Bereich. Beachten Sie, dass, obwohl das Array selbst ein veränderlicher Typ, wäre effektiv unveränderlich jedes Array wäre Instanz, die jemals auf dem Gebiet gespeichert werden würde, da sie nie von einem Code zugänglich sein würden, dass es mutieren könnte.

Beachten Sie, dass Szenario # 1 ziemlich häufig mit generischen Typen ist; zum Beispiel, ist es sehr üblich, ein Wörterbuch zu haben, deren „Werte“ sind die Identitäten der veränderbaren Objekte; dass Wörterbuch Aufzählen wird Fälle von KeyValuePair deren Value Rück Feld besagt, dass wandelbar Typ.

Szenario 2 ist weniger verbreitet. Es gibt leider keine Möglichkeit, den Compiler zu sagen, dass Methoden struct andere als Eigenschaft Setter wird eine Struktur und ihre Verwendung ändern sollte daher im schreibgeschützten Kontext verboten werden; man könnte eine Struktur hat, die wie ein List<T> benommen, aber mit dem Wert Semantik und eine Add Methode enthalten, aber einen Versuch Add auf einer Nur-Lese-Struktur-Instanz zu nennen eher falschen Code erzeugen würde als ein Compiler-Fehler. Des Weiteren wird mutiert Methoden und Eigentum Setter auf solche Strukturen im Allgemeinen eher schlecht ab. Solche Strukturen können nützlich sind, wenn sie auf einer ansonsten wandelbar Klasse als unveränderlichen Wrapper existieren; wenn eine solche Struktur nie geboxt wird, die Leistung wird oft besser als eine Klasse. Wenn genau einmal verpackt (beispielsweise durch zu einem Schnittstellentyp umgewandelt wird), die Leistung wird im Allgemeinen zu einer Klasse vergleichbar sein. Wenn immer wieder geboxt, kann die Leistung viel schlimmer als eine Klasse.

Es ist wahrscheinlich nicht empfohlen, dies zu tun: siehe http://msdn.microsoft.com/en-us/library/ms229017 (VS.85) aspx

  

Referenztypen sind auf dem Heap zugewiesen und Speicherverwaltung   vom Garbage Collector behandelt.

     

Werttypen werden auf dem Stack oder Inline zugeordnet und werden ausgeplant   wenn sie gehen, den Gültigkeitsbereich.

     

In der Regel sind Werttypen billiger zuzuordnen und ausplanen.   Wenn sie jedoch in Szenarien eingesetzt werden, erfordern, dass eine signifikante   Menge des Boxens und Unboxing, führen sie schlecht im Vergleich zu   Referenztypen.

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