2010-09-16 19 views
27

in un file che ho definito una struttura pubblicaproblema con struct e proprietà in C#

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

In un altro ho provato a fare questo:

class Test 
{ 
    mystruct my_va; 

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

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

Intellisense riconosce My_va.struct1 ma compilatore dice

Errore 1 Impossibile modificare il valore di ritorno di 'TEST.mystruct' perché non è un variabile

Come correggere la sintassi?

risposta

32

Si consiglia vivamente di evitare le strutture mutevoli. Esibiscono ogni sorta di comportamento sorprendente.

Soluzione: rendere la vostra struttura immutabile.

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

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

Usage:

class Test 
{ 
    private MyStruct myStruct; 

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

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

@Caspar Kleijne: Valore1 e Valore2 sono campi, non proprietà automatiche. Quindi, no. – dtb

+1

ok, scusa .... i campi pubblici sono brutti .... –

+1

Grazie funziona ma puoi spiegare PERCHÉ la tua sintassi funziona e non la mia, non riesco davvero a capire la differenza fondamentale: perché rendendolo readonly ha qualcosa da fare con l'impostazione del valore della proprietà? – user310291

47

Sì, è assolutamente giusto. Vedete, quando si ottiene prelevaMy_va, si sta recuperando un valore - una copia del valore corrente di my_va. Cambiare quel valore non avrebbe alcun vantaggio, perché avresti immediatamente scartato la copia. Il compilatore ti impedisce di scrivere codice che non fa quello che sembra.

In generale, evitare le strutture mutabili. Sono cattivi In questo caso, si potrebbe (per esempio) il cambiamento mystruct di essere immutabile, ma con un metodo come questo:

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

quindi modificare il codice di costruzione per:

My_va = My_va.WithStruct1(10); 

... anche se in questo caso è molto più probabile (dato che sei in un costruttore) che si dovrebbe scrivere:

My_va = new mystruct(10, 0); 

Non solo si dovrebbe struct b E immutabile, dovrebbero essere piuttosto rari nella maggior parte delle codebase, IMO. Oltre a Noda Time, non ho quasi mai scritto i miei tipi di valori personalizzati.

Infine, si prega di imparare la .NET naming conventions e cercare di seguirli, anche per il codice di esempio :)

+26

Ho sentito raccontare una struttura mutevole che brucia un intero villaggio. Era una follia. –

+22

@Anthony: "Una volta hai sentito un racconto"? Lo fai sembrare come se non ci credessi. Ero lì e ho visto tutto. Mi tormenta ancora di notte. –

+8

Anakin Skywalker è stato bello fino a quando non ha imparato a conoscere le strutture mutevoli. – Josh

3

più semplice correzione: Modificare la struttura per una classe.

2

Lavoro con un elenco di strutture e l'ho risolto in un modo diverso.

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

Ora, quando voglio impostare un codice di valore che in questo modo:

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

Il codice è un po 'strano, forse, ma si risolve il problema. Risolve il problema che a una struttura non può essere assegnato direttamente un singolo valore, ma può essere una copia di un tipo simile. solving errore 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

Il codice non sembra affatto strano. Piuttosto, è l'approccio giusto se uno non è in grado o non vuole usare una serie di strutture. Alcune persone non amano le strutture mutevoli, perché non si comportano come oggetti, ma nei casi in cui si desidera un gruppo di variabili bloccato insieme con del nastro adesivo direi che è meglio usare un mucchio di variabili incollate insieme con del nastro adesivo che provare a fare in modo che una struttura si comporti come una mediocre imitazione di un oggetto che sta facendo una cattiva imitazione di un gruppo di variabili incollate insieme con del nastro adesivo. L'unica cosa che noterei ... – supercat

+0

...è che potrebbe essere più comodo ed efficiente sostituire 'Lista PixelList' con 'Pixel [] Pixels = new Pixel [16];/* O qualche ragionevole default */int PixelCount; ', e aggiungi' void AddPixel (Pixel newPixel) {if (PixelCount> = Pixels.Count) Pixel = Array.Resize (ref Pixel, PixelCount * 2); Pixel [PixelCount] = newPixel; PixelCount ++; } '. Ciò consentirà di aggiornare gli elementi dell'array sul posto. – supercat

+0

il tuo diritto, lo uso in un codice "multi-threading" pericoloso, come un elenco di variabili globali. esco dalla zona di pericolo, perché il mio codice funziona molto velocemente usando le strutture. Non penso che le strutture dovrebbero essere usate troppo, ma in casi strani faccio cose strane con dati pointcloud su hardware dedicato, quindi potrebbe essere meglio; prima di usare una struttura, consiglio alle persone di guardare se ne hanno veramente bisogno. Velocità e bassi consumi di memoria, potrebbe essere un motivo. – user613326

1

Purtroppo questo errore può essere generato in modo non corretto quando si assegna ad una proprietà (cioè chiamando una setter proprietà). Una struttura immutabile può ancora avere un setter di proprietà valido, purché il setter di proprietà non assegni effettivamente alcun campo nella struct. Ad esempio,

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

L'errore "CS 1612 dovrebbe essere un avvertimento. Come posso riportarlo a Microsoft in modo che venga corretto? Non voglio usare una lezione perché, ovviamente, ciò comporta un sovraccarico che non è appropriato nel mio caso. –