2011-09-02 20 views
9

Eventuali duplicati:
Modify Struct variable in a DictionaryAssegnazione dei campi/proprietà in una struttura

Perché è che

MyStruct test = new MyStruct(); 
    test.Closed = true; 

funziona bene, ma

MyDictionary[key].Closed = true; 

Mostra un errore "Impossibile modificare l'espressione perché non è una variabile" in fase di compilazione?

Perché è diverso il compito in questi due casi?

Nota: MyDictionary è di tipo <int, MyStruct>

Codice in materia di struct:

public struct MyStruct 
{ 
    //Other variables 
    public bool Isclosed; 
    public bool Closed 
    { 
     get { return Isclosed; } 
     set { Isclosed = value; } 
    } 
//Constructors 
} 
+0

Mostra altro codice .. – Zabba

+0

@Zabba, modificato per più codice. – soandos

+0

Commento di downvoter per favore? – soandos

risposta

12

perché MyDictionary[key] restituisce una struct, è davvero tornando un copia dell'oggetto nella raccolta, non il oggetto reale che è ciò che accade quando usi una classe. Questo è ciò di cui il compilatore ti avvisa.

Per risolvere questo, dovrete re-impostare MyDictionary[key], forse in questo modo:

var tempObj = MyDictionary[key]; 
tempObj.Closed = true; 
MyDictionary[key] = tempObj; 
+0

Ma allora avrei bisogno di chiamare di nuovo l'intero costruttore no? Non c'è modo di cambiare parte di una struttura in questa situazione? – soandos

+0

Ho modificato il mio esempio per riutilizzare lo stesso oggetto invece di crearne uno nuovo. – Keith

+1

@soandos struct viene sempre copiata quando viene passata da un metodo all'altro, quindi "whole constructor" sta accadendo tutto il tempo (ad esempio quando si accede alla struct digitando tale dict), ecco perché si consiglia di non avere struct più grande di 16 byte –

1

Cambiare la struttura per essere una classe, invece ...

class Program 
{ 
    static void Main(string[] args) 
    { 
     dic = new Dictionary<int, MyStruct>(); 

     MyStruct s = new MyStruct(){ Isclosed=false}; 

     dic.Add(1,s); 

     dic[1].Isclosed = true; 

     Console.WriteLine(dic[1].Isclosed.ToString()); //will print out true... 
     Console.Read(); 
    } 

    static Dictionary<int, MyStruct> dic; 

    public class MyStruct 
    { 
     public bool Isclosed; 
     public bool Closed 
     { 
      get { return Isclosed; } 
      set { Isclosed = value; } 
     } 
    } 
} 
+0

So che le strutture sono più efficienti quando si gestiscono diversi oggetti che contengono fondamentalmente campi come la tua struct ma se ti capita di istanziare alcuni oggetti, la creazione di una classe ti farà risparmiare alcune linee di codice :) –

+0

Quando usi una struttura di campo esposto con raccolte predefinite diverse dagli array, è necessario copiare la struttura, modificarla e quindi memorizzarla. Una seccatura, ma la semantica è prevedibile; 'dic [1] .Isclosed' sarà sempre indipendente da dic [0] .Isclosed'. Dicendo 'dic [0] = dic [1];' copierà lo stato di dic [0] 'senza collegare i due elementi insieme. Se si usa una classe mutevole, si può scrivere 'dic [1] .Isclosed = true;' ma ciò non significa che fare ciò produrrà il comportamento desiderato. Un oggetto che incapsula il suo stato negli stati degli oggetti mutabili contenuti in una raccolta deve ... – supercat

+0

... in genere evitare che qualsiasi riferimento agli oggetti in questione raggiunga il codice esterno.Ciò significa copiare in modo difensivo tutti i dati in arrivo da memorizzare nella raccolta e copiare o avvolgere in modo difensivo qualsiasi dato letto da esso. Le strutture eseguono automaticamente copie difensive durante la lettura o la scrittura di dati, ma le operazioni di copia su una struttura di qualsiasi dimensione sono molto più economiche di tali operazioni su una classe della stessa dimensione. La differenza di costo è maggiore per le piccole strutture, ma rimane significativa fino a quando le strutture diventano molto grandi. – supercat

Problemi correlati