2010-09-16 21 views
27

en un archivo que define una estructura públicaProblema con estructura y propiedades en C#

public struct mystruct 
{ 
    public Double struct1; 
    public Decimal struct2; 
} 

En otro Traté de hacer esto:

class Test 
{ 
    mystruct my_va; 

    public mystruct my_va 
    { 
     get { return my_va; } 
     set { my_va = value; } 
    } 

    public Test() 
    { 
     my_va.struct1 = 10; 
    } 
} 

Intellisense reconoce My_va.struct1 pero compilador dice

Error 1 No se puede modificar el valor de retorno de 'TEST.mystruct' porque no es un variable

Cómo corregir la sintaxis?

Respuesta

32

Es muy recomendable para evitar estructuras mutables. Exhiben todo tipo de comportamiento sorprendente.

Solución: Haga que su estructura sea inmutable.

public struct MyStruct 
{ 
    public readonly double Value1; 
    public readonly decimal Value2; 

    public MyStruct(double value1, decimal value2) 
    { 
     this.Value1 = value1; 
     this.Value2 = value2; 
    } 
} 

Uso:

class Test 
{ 
    private MyStruct myStruct; 

    public Test() 
    { 
     myStruct = new MyStruct(10, 42); 
    } 

    public MyStruct MyStruct 
    { 
     get { return myStruct; } 
     set { myStruct = value; } 
    } 
} 
+1

@Caspar Kleijne: Value1 y Value2 son campos, no propiedades automáticas. Entonces, no. – dtb

+1

right, sorry .... los campos públicos son feos .... –

+1

Gracias que funciona, pero ¿puedes explicar por qué tu sintaxis funciona y no la mía, realmente no puedo entender la diferencia fundamental: por qué al hacerlo de forma legible tiene algo que ver con hacer con establecer el valor de la propiedad? – user310291

47

Sí, está en lo cierto. Usted ve, cuando buscaMy_va, está obteniendo un valor - una copia del valor actual de my_va. Cambiar ese valor no tendría ningún beneficio, porque descartaría la copia inmediatamente. El compilador le impide escribir código que no funciona como lo hace.

En general, evite las estructuras mutables. Ellos son malvados En este caso, usted podría (por ejemplo) el cambio mystruct que son inmutables, pero con un método como este:

public mystruct WithStruct1(double newValue) 
{ 
    return new mystruct(newValue, struct2); 
} 

a continuación, cambiar su código de constructor para:

My_va = My_va.WithStruct1(10); 

... aunque en este caso es mucho más probable (teniendo en cuenta que estás en un constructor) que se debe escribir:

My_va = new mystruct(10, 0); 

no sólo debe structs b e inmutables, deberían ser bastante raros en la mayoría de las bases de código, IMO. Aparte de Noda Time, casi nunca he escrito mis propios tipos de valores personalizados.

Por último, por favor, aprender el .NET naming conventions y tratar de seguir, incluso para el código de ejemplo :)

+26

Una vez escuché la historia de una estructura mutable que quemaba un pueblo entero. Twas locura –

+22

@Anthony: ¿"escuchaste una vez un cuento"? Haces que parezca que no lo crees. Yo estaba allí, y lo vi todo. Todavía me atormenta por la noche. –

+8

Anakin Skywalker estuvo genial hasta que descubrió las estructuras mutables. – Josh

3

solución más simple: Cambiar la estructura de una clase.

2

Trabajo con una lista de estructuras, y la solucioné de otra manera.

struct Pixel 
{ Public int X; 
    Public int C; 
} 
List<Pixel> PixelList = new List<Pixel> 
TempPixel = new Pixel(); 

Ahora cuando quiero establecer un código de valor i de esta manera:

TempPixel = PixelList[i]; 
TempPixel.X= 23; // set some value 
PixelList[i] = TempPixel 

El código es un poco extraño tal vez, pero que resuelve el problema. Resuelve el problema de que a una estructura no se le puede asignar directamente un solo valor, pero puede ser una copia de un tipo similar. resolución de error CS1612:

https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28CS1612%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV2.0%22%29;k%28DevLang-CSHARP%29&rd=true

+1

El código no parece extraño. Más bien, es el enfoque correcto si uno no puede o no quiere usar una matriz de estructuras. A algunas personas les disgustan las estructuras mutables, porque no se comportan como objetos, pero en los casos en que uno quiere un conjunto de variables pegadas con cinta adhesiva, diría que es mejor usar un conjunto de variables pegadas con cinta adhesiva que tratar de hacer que una estructura se comporte como una imitación mediocre de un objeto que está haciendo una pobre imitación de un conjunto de variables pegadas con cinta adhesiva. La única cosa que notaría ... – supercat

+0

...es que puede ser más conveniente y eficiente reemplazar 'List PixelList' con' Pixel [] Pixels = new Pixel [16];/* O algunos valores predeterminados razonables */int PixelCount; ', y agrega' void AddPixel (Pixel newPixel) {if (PixelCount> = Pixels.Count) Pixels = Array.Resize (ref Pixels, PixelCount * 2); Pixels [PixelCount] = newPixel; PixelCount ++; } ' Hacer eso permitirá que los elementos de la matriz se actualicen en el lugar. – supercat

+0

a su derecha, lo uso en algún código multihilo 'peligroso', como una lista variable global. Salgo de la zona de peligro, porque mi código se ejecuta muy rápido usando structs. No creo que las estructuras se usen demasiado, pero en casos raros hago cosas extrañas con datos de la nube de puntos en hardware dedicado, entonces podría ser mejor; antes de usar una estructura, recomiendo a las personas que miren si realmente lo necesitan. La velocidad y el bajo consumo de memoria pueden ser una razón. – user613326

1

Desafortunadamente este error se puede generar de forma incorrecta cuando se asigna a una propiedad (es decir, la invocación de un regulador de la propiedad). Una estructura inmutable puede tener un definidor de propiedad válido, siempre que el establecimiento de la propiedad no asigne realmente ningún campo en la estructura. Por ejemplo,

public struct Relay 
{ 
    public Relay(Func<string> getText, Action<string> setText) 
    { 
     this.GetText = getText; 
     this.SetText = setText; 
    } 
    private readonly Func<string> GetText; 
    private readonly Action<string> SetText; 

    public string Text { 
     get { return this.GetText(); } 
     set { this.SetText(value); } 
    } 
} 

class Example 
{ 
    private Relay Relay { 
     get { return new Relay(() => this.text, t => { this.text = t; }); } 
    } 

    private string text; 


    public Method() 
    { 
     var r = new Relay(); 
     r.Text = "hello"; // not a compile error (although there is a null reference) 

     // Inappropriately generates a compiler error 
     this.Relay.Text = "hello"; 

     r = this.Relay; 
     r.Text = "hello"; // OK 
    } 
} 
+0

El "error" CS 1612 debería ser una advertencia. ¿Cómo puedo devolver esto a Microsoft para que lo solucione? No quiero usar una clase porque, obviamente, eso implica una sobrecarga que no es apropiada en mi caso. –