2011-09-02 16 views
9

Duplicar posibles:
Modify Struct variable in a DictionaryAsignación de campos/propiedades en una estructura

Por qué es que

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

Funciona muy bien, pero

MyDictionary[key].Closed = true; 

Muestra un error "No se puede modificar la expresión porque no es una variable" en el momento de la compilación?

¿Por qué es diferente la asignación en estos dos casos?

Nota: MyDictionary es de tipo <int, MyStruct>

Código para la estructura:

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

Mostrar más código .. – Zabba

+0

@Zabba, editado para obtener más código. – soandos

+0

Comentario de downvoter por favor? – soandos

Respuesta

12

Debido MyDictionary[key] vuelve una estructura, que es realmente devolviendo una copia del objeto de la colección, no el objeto real que es lo que sucede cuando usas una clase. De esto es de lo que el compilador te está advirtiendo.

Para evitar esto, usted tiene que volver a ajustar MyDictionary[key], tal como esto:

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

Pero entonces tendría que llamar al constructor entero, ¿no? No hay forma de cambiar parte de una estructura en esta situación? – soandos

+0

Modifiqué mi ejemplo para reutilizar el mismo objeto en lugar de crear uno nuevo. – Keith

+1

@soandos struct siempre se copia cuando se pasa entre métodos, por lo que el "constructor completo" está sucediendo todo el tiempo (por ejemplo, cuando accede a su estructura por clave en ese dict), por eso se recomienda no tener una estructura mayor a 16 bytes –

1

Cambiar la estructura a ser una clase en lugar ...

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

Sé que las estructuras son más eficientes cuando se trata de varios objetos que básicamente contienen campos como su estructura, pero si solo instancia algunos objetos, crear una clase le ahorrará algunas líneas de código :) –

+0

Al usar una estructura de campo expuesto con colecciones integradas distintas de las matrices, se debe copiar la estructura, modificarla y luego almacenarla de nuevo. Una molestia, pero la semántica es predecible; 'dic [1] .Isclosed' siempre será independiente de' dic [0] .Isclosed'. Diciendo 'dic [0] = dic [1];' copiará el estado de 'dic [0]' sin unir los dos elementos. Si uno usa una clase mutable, se puede escribir 'dic [1] .Isclosed = true;' pero eso no significa que se obtendrá el comportamiento deseado. Un objeto que encapsula su estado en los estados de los objetos mutables contenidos en una colección debe ... – supercat

+0

... generalmente evitar que las referencias a los objetos en cuestión lleguen al código externo.Esto significa copiar a la defensiva cualquier información entrante que se almacenará en la colección, y copiar o copiar de forma defensiva cualquier dato leído. Las estructuras realizan automáticamente copias defensivas cuando leen o escriben datos, pero las operaciones de copia en una estructura de cualquier tamaño son mucho más económicas que las operaciones de ese tipo en una clase del mismo tamaño. La diferencia en el costo es mayor para las estructuras pequeñas, pero sigue siendo significativa hasta que las estructuras sean muy grandes. – supercat

Cuestiones relacionadas