Domanda

È possibile in C# per avere una Struttura con una variabile membro che è un tipo di Classe?Se è così, dove le informazioni vengono memorizzati, nello Stack, Heap, o entrambi?

È stato utile?

Soluzione

Sì, è possibile.Il puntatore alla variabile membro della classe è memorizzato sullo stack con il resto della struttura i valori, e l'istanza della classe vengono memorizzati nello heap.

Le strutture possono contenere anche le definizioni di classe come membri (classi interne).

Ecco alcune davvero inutili codice che almeno si compila e si esegue per mostrare che è possibile:

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;
            }
        }
    }
}

Altri suggerimenti

Il contenuto di classe viene memorizzato sul mucchio.

Un riferimento alla classe (che è quasi lo stesso come un puntatore) viene memorizzato con la struttura del contenuto.Dove la struttura è memorizzato il contenuto dipende dal fatto che è una variabile locale, parametro di metodo o il membro di una classe, e se è stato boxed o catturati da una chiusura.

Se uno dei campi di una struct è un tipo di classe, che in campo si sia premuto il identità di un oggetto di classe o altro null fonte.Se la classe oggetto in questione è immutabile (ad es. string), memorizzando la sua identità in modo efficace anche archiviare i propri contenuti.Se la classe oggetto in questione è mutevole, tuttavia, la memorizzazione, l'identità, sarà un mezzo efficace per la memorizzazione di contenuti se e solo se il riferimento non cadrà mai nelle mani di un qualsiasi codice che potrebbe mutare una volta memorizzata nel campo.

In generale, si dovrebbe evitare di memorizzare mutevole tipi di classe all'interno di una struttura a meno che una delle due situazioni:

  1. Ciò a cui si è interessati è, infatti, l'identità dell'oggetto di classe piuttosto che il suo contenuto.Per esempio, si potrebbe definire un `FormerControlBounds` la struttura che contiene i campi di tipo `Controllo` e `Rettangolo` e rappresenta i `Limiti` che il controllo fosse a un certo momento nel tempo, al fine di essere in grado, successivamente, di ripristinare il controllo della sua precedente posizione.Lo scopo del `Controllo` di campo non sarebbe di tenere una copia del controllo dello stato, ma piuttosto per identificare il controllo, la cui posizione deve essere ripristinato.Generalmente la struttura dovrebbe evitare l'accesso a qualsiasi mutevole membri dell'oggetto a cui si tiene di riferimento, salvo i casi in cui è chiaro che tale accesso sia in riferimento all'attuale stato mutabile dell'oggetto in questione (es.in un `CaptureControlPosition` o `RestoreControlToCapturedPosition` un metodo o un `ControlHasMoved di proprietà).
  2. Il campo è `privato`, gli unici metodi che leggere farlo al fine di esaminare la sua proprietà senza esporre l'oggetto di per sé al di fuori del codice, e gli unici metodi che scrivere, viene creato un nuovo oggetto, eseguire tutte le mutazioni che sono sempre andando a succedere, e quindi memorizzare un riferimento a tale oggetto.Si potrebbe, ad esempio, la progettazione di una `struttura` che si comporta più o meno come un array, ma con valore semantica, avendo il struct contenere un array in un campo privato, e facendo ogni tentativo di scrivere la matrice di creare un nuovo array con i dati del vecchio, modificare il nuovo array, e memorizzare array modificato quel campo.Si noti che anche se la matrice stessa sarebbe un mutevole tipo, ogni istanza array che sarebbe mai essere memorizzati nel campo vorresti essere efficacemente immutabile, che non sarebbe mai essere accessibile da qualsiasi codice che potrebbe mutare di esso.

Nota che scenario #1 è abbastanza comune con i tipi generici;per esempio, è molto comune avere un dizionario in cui i "valori" sono le identità di oggetti mutabili;l'enumerazione che il dizionario verrà restituito istanze di KeyValuePair cui Value campo sostiene che mutevole tipo.

Scenario #2 è meno comune.Non c'è purtroppo alcun modo per dire al compilatore che struct metodi diversi da quelli di proprietà setter modificare una struttura e il loro uso deve quindi essere vietato in sola lettura contesti;si potrebbe avere una struttura che si comportava come un List<T>, ma con valore semantica, ed ha incluso un Add il metodo, ma un tentativo di chiamata Add su una sola struttura in grado di generare falsi codice piuttosto che un errore del compilatore.Inoltre, la mutazione metodi e proprietà setter su tali strutture sono generalmente eseguire piuttosto male.Tali strutture possono essere utili sono, se esistono, come una immutabile wrapper altrimenti-mutevole classe;se una struttura non è mai boxed, le prestazioni sono spesso meglio di una classe.Se boxed esattamente una volta (ad es.dal cast di un tipo di interfaccia), le prestazioni sono generalmente paragonabili a una classe.Se boxed ripetutamente, le prestazioni possono essere molto peggio di una classe.

Probabilmente non è una pratica consigliata per farlo:vedere http://msdn.microsoft.com/en-us/library/ms229017(VS.85).aspx

Tipi di riferimento sono allocati nel mucchio, e la gestione della memoria è gestito dal garbage collector.

I tipi di valore vengono allocate sullo stack o in linea e vengono deallocati quando escono dall'ambito.

In generale, i tipi di valore sono più economici di allocare e deallocare.Tuttavia, se vengono utilizzati in scenari che richiedono un significativo quantità di boxing e unboxing, lavorano male rispetto a tipi di riferimento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top