2009-02-04 9 views
6

Consente di considerare che ho una proprietà pubblica denominata AvatarSize come il seguente,impostazione proprietà di immobile direttamente in C#

public class Foo 
{ 
    ... 

    public Size AvatarSize 
    { 
    get { return myAvatarSize; } 
    set { myAvatarSize = value; } 
    } 

    ... 
} 

Ora, se una classe di destinazione vuole impostare questa proprietà, quindi hanno bisogno di farlo nel modo seguente ,

myFoo.AvatarSize = new Size(20, 20); //this is one possible way 

Ma se provo a impostare in questo modo,

myFoo.AvatarSize.Height = 20; //.NET style 
myFoo.AvatarSize.Width = 20; //error 

il compilatore farmi un errore affermando che non può modificare i valori di ritorno. So perché succede, ma mi piacerebbe che anche il secondo supporto fosse supportato. Per favore aiutami con una soluzione.

P.S. Scusate se il titolo è assurdo

+0

Puoi specificare perché vuoi che funzioni in questo modo? Temo che non ci siano molte opzioni, oltre a ciò che ha detto Petoj. –

+0

Si prega di mostrare come appare "Dimensioni". –

+0

Size è un tipo di valore .Net standard nello spazio dei nomi System.Drawing. – bang

risposta

10

Size è una struttura. Essere un ValueType è immutabile. Se si modifica la proprietà in questo modo, modificherà solo un'istanza dell'oggetto nello stack, non il campo effettivo. Nel tuo caso la proprietà AvatarSize può essere impostata solo utilizzando un costruttore di struct: new Size(20, 20).

+0

Non è in realtà l'immutabilità a rendere questo un problema - anche se si trattasse di una struttura mutevole, avresti comunque lo stesso problema perché il valore restituito dalla proprietà sarebbe dissociato dalla variabile stessa. –

+0

In realtà, l'OP ha detto che sa perché il problema si verifica. Presumo che stia solo cercando di fare meno digitando quando deve solo impostare una delle proprietà ... Quindi, la mia risposta era di avvolgerla in una classe. Non penso che sia davvero la migliore idea per farlo, ma se lo vuoi davvero, può essere fatto. –

2

Si potrebbe creare 2 nuove proprietà myFoo.AvatarSizeWidth e rendono questo cambiamento di proprietà della stessa larghezza vale per Altezza ..

+0

Non voglio averlo in quel modo. Non risolverà, myFoo.AvatarSize.Height = 20; //.NET style myFoo.AvatarSize.Width = 20; // errore questo numero –

+0

@Sudarsan: hai frainteso la risposta. Ti suggerisco di scrivere myFoo.AvatarSizeHeight = 20. –

1

fa queste dimensioni dell'oggetto avere proprietà di scrittura per altezza e larghezza? O sono di sola lettura?

+0

Hanno proprietà di scrittura –

+0

No. La dimensione è imutibile. Non puoi modificare nessuno dei suoi valori. Ecco perché il compilatore geme. –

4

L'unico modo che si può fare quello che vuoi è definendo

public class MutableSize{ 
    public int Height{get;set;} 
    public int Width{get;set;} 
} 

e poi dover tornare AvatarSize uno di quelli invece di Dimensioni.

2

L'unico modo è quello di creare il proprio tipo di dimensione come classe (riferimento) anziché come struct (valore).

public class Size 
    { 
    public Int32 Width; 
    public Int32 Height; 
    } 

Ma questo sarà ovviamente rendere la dimensione perdere alcuni dei vantaggi di essere un tipo di valore ...

1

Se si vuole trattare una struttura come una classe, si deve fare una classe wrapper che ha una conversione implicita al tipo struct. Sotto puoi vedere la classe wrapper (di nome Size, puoi chiamarla come vuoi, non importa), la classe Class1 che ha una proprietà Size e poi un esempio di come è stata utilizzata nella classe Form1:

EDIT: Ho aggiornato la classe Size con la conversione inversa (da System.Drawing.Size a questa classe Size) e alcuni commenti.

public class Size 
{ 
    public Size(){} 

    public Size(int width, int height) 
    { 
     this.Width = width; 
     this.Height = height; 
    } 

    public int Width { get; set; } 

    public int Height { get; set; } 

    static public implicit operator System.Drawing.Size(Size convertMe) 
    { 
     return new System.Drawing.Size(convertMe.Width, convertMe.Height); 
    } 

    static public implicit operator Size(System.Drawing.Size convertMe) 
    { 
     return new Size(convertMe.Width, convertMe.Height); 
    } 
} 

class Class1 
{ 
    public Class1() 
    { 
     this.TheSize = new Size(); 
    } 

    public Size TheSize { get; set; } 
} 

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     /// Style 1. 
     Class1 a = new Class1(); 

     a.TheSize = new Size(5, 10); 

     /// Style 2. 
     Class1 c = new Class1(); 

     c.TheSize.Width = 400; 
     c.TheSize.Height = 800; 

     /// The conversion from our Size to System.Drawing.Size 
     this.Size = c.TheSize; 

     Class1 b = new Class1(); 

     /// The opposite conversion 
     b.TheSize = this.Size; 

     Debug.Print("b Size: {0} x {1}", b.TheSize.Width, b.TheSize.Height); 


    } 
} 
+0

Se questa è la casse, allora come gestisco Add() per una proprietà di tipo IList ?? Ad esempio, come posso consentire l'utilizzo di myFoo.AvatarList = new IList () anche myFoo.AvatarList.Add ("foo"); Se dovessi seguire la tua strada, allora diventa noioso vero ?? –

+0

Mi dispiace, non vedo come ciò si riferisca alla domanda originale. La tua domanda riguardava la proprietà AvatarSize, non c'era nulla su una lista. –

+0

Vedere la classe Form1 nel mio codice, fa tutto ciò che hai chiesto. –

4

Questa è solo un'espansione di Petoj's answer. Non andrei per una dimensione mutabile - rendere le cose mutabili porta a capire il codice più difficile da capire.

invece, introdurre due nuove proprietà, AvatarHeight e AvatarWidth:

public class Foo 
{ 
    ... 

    public Size AvatarSize 
    { 
    get { return myAvatarSize; } 
    set { myAvatarSize = value; } 
    } 

    public int AvatarHeight 
    { 
    get { return AvatarSize.Height; } 
    set { AvatarSize = new Size(AvatarWidth, value); } 
    } 

    public int AvatarWidth 
    { 
    get { return AvatarSize.Width; } 
    set { AvatarSize = new Size(value, AvatarHeight); } 
    } 

    ... 
} 

Ancora non può scrivere myFoo.AvatarSize.Width = 20 ma si può scrivere myFoo.AvatarWidth = 20. Tieni presente che impostare separatamente larghezza e altezza sarà meno efficiente rispetto a impostarli in una volta sola.

Questo è l'approccio che Windows Form prende, tra l'altro.