2010-09-20 17 views
8

Probabilmente c'è una spiegazione abbastanza logica a questo, ma ho una domanda.Differenza tra la modifica di una variabile e una proprietà

Diciamo che ho una variabile di tipo Rectangle chiamata _rect. Ora posso dire _rect.X = 50; senza alcun problema.

Ora ho una classe con una proprietà chiamata Rect che espone la variabile interna _rect.

Poi, se provo a scrivere Rect.X = 50; ottengo il seguente errore di compilazione:

non può modificare il valore di ritorno di 'TestClass.Rect' perché non è una variabile.

Posso scrivere Rect = new Rectangle(50, Rect.Y, Rect.Width, Rect.Height) come per un tipo immutabile, ma per tipi non immutabili, c'è un altro modo per farlo?

Desidero utilizzare le proprietà automatiche per questo campo rettangolo, ma è davvero fastidioso non poterlo modificare all'interno della classe stessa.

C'è qualche modo per creare un backing field e rilasciare la proprietà automatica?

+0

ci mostri il codice per la classe Rect? E perché non usi la classe Rect integrata? –

+0

Rectangle è una classe o una struct? Se si tratta di una struttura, prova a trasformarla in una classe – Rohith

+0

Forniscici un elenco completo del codice, è difficile per me illustrare ciò che stai dicendo e questo potrebbe aiutare a chiarire la tua domanda. –

risposta

10

Il motivo di questo errore è dovuto al fatto che Rectangle è un tipo di valore (struct) in contrasto con i tipi di riferimento (classi). Non è possibile modificare la proprietà X perché quando si utilizza il getter di proprietà Rect viene restituito un nuovo valore per il rettangolo (il getter è una funzione). Se era un tipo di riferimento, stai manipolando il puntatore e questo sarebbe possibile.

Questo è un aspetto importante del valore rispetto ai tipi di riferimento da tenere presente.

+0

Per essere sicuri, non esiste un motivo * tecnico * per cui il compilatore non ha potuto farlo funzionare.Il compilatore genera tutti i tipi di codice extra per l'utente (ad es. Boxe), quindi perché non qui? (In effetti, la ragione è probabilmente che non è considerata importante dal momento che le strutture dovrebbero essere comunque immutabili.) –

+0

@Konrad: le strutture vengono copiate quando vengono passate di conseguenza, quindi l'operazione semplicemente non avrebbe alcun senso. Non è a causa dell'immutabilità (le strutture sono mutabili). Ma se recuperi una copia di un oggetto e cambi il campo in quella copia, è semplicemente un NOOP. – viraptor

+0

@viraptor: non sono d'accordo. L'operazione ha ovviamente un senso: mutare una proprietà. Il compilatore potrebbe facilmente farlo funzionare generando codice equivalente a 'var tmp = foo.Property; tmp.x = newX; foo.Property = tmp; '- Il compilatore in realtà ** fa ** questo per una situazione equivalente: quando hai una proprietà di tipo value e scrivi' foo.Property + = 1' questo ** funziona ** (testato sul compilatore Mono). Il compilatore riscrive chiaramente il codice di cui sopra. –

1

L'accesso alla proprietà è in realtà una chiamata di funzione che restituisce una copia del tipo di valore. Rect.X = 50; modificherebbe solo questa copia temporanea, non il campo di supporto stesso.

Quando la proprietà non viene implementata automaticamente, è possibile creare una proprietà aggiuntiva RectX, che può essere utilizzata per ottenere e impostare la proprietà X del rettangolo.

+0

Mi sento veramente stupido ora, per non capire perché il nuovo Rettangolo (...) ha funzionato, e non Rect.X = 50, poiché entrambi avrebbero funzionato sulla copia, ma quando scrivo il nuovo Rettangolo sto chiamando il set invece di ottenere. Grazie per aver reso la mia testa chiara riguardo a questo. Quindi in pratica significa no allora. Se voglio quel tipo di comportamento, devo usare un campo di supporto. –

+0

Quando si utilizza un campo di supporto, il comportamento sarà sempre lo stesso, getter e setter continuano ad essere metodi, quindi si otterrà una copia del valore dell'istanza Rectangle. Il comportamento che si desidera è solo per i tipi di riferimento, perché in questo caso si ottiene il "riferimento" all'istanza dell'oggetto originale. Tuttavia il rettangolo è un tipo di valore. –

0
class RectangleWithoutFields 
    { 
    // just autoproperties, no fields 

    public int X { get; set; } 

    public int Y { get; set;} 


    public RectangleWithoutFields() 
    { 
     X = 0; 

     Y = 0; 
    } 

    public void ChangeProperties(int x, int y) 

    { 
     X = x; 

     Y = y; 
    } 
} 
+0

Non ero cercando di creare un nuovo rettangolo qui, ma per farlo funzionare con il rettangolo standard :) –

Problemi correlati