2013-06-02 23 views
5

ho una proprietà definita come ...C# Proprietà con getter codificato duro e setter

public List<Obj> Objs { get; set; } 

Quello che mi piacerebbe essere in grado di fare è quello di mettere un po 'di logica nel metodo get, quindi sarebbe guardare qualcosa di simile ...

public List<Obj> Objs 
{ 
    get 
    { 
     if (Objs == null) 
     { 
      Objs = new List<Obj>(); 
     } 
     if (Objs.Count < 1) 
     { 
      Objs.Add(new Obj()); 
     } 
     return Objs; 
    } 
    set { Objs = value; } 
} 

Ora, quando faccio questo ottengo un errore che mi dice che la funzione è ricorsiva su tutti i percorsi.

C'è un modo per farlo senza creare un backing field privato?

+1

Non farlo.http://msdn.microsoft.com/en-us/library/ms182327.aspx – SLaks

+1

Perché non puoi farlo con un backing field? – Default

+0

È incredibile come siano le persone creative quando si tratta di abusare di un sistema con cui stanno lavorando. E fortunatamente per te il compilatore è stato abbastanza intelligente da sapere che stai cercando di abusare del sistema, altrimenti la domanda sarebbe stata "perché la mia app è appesa" –

risposta

12

È necessario per fare un campo privato:

private List<Obj> _objs; 
    public List<Obj> Objs 
    { 
     get 
     { 
      if (_objs== null) 
      { 
       _objs= new List<Obj>(); 
      } 
      if (_objs.Count < 1) 
      { 
       _objs.Add(new Obj()); 
      } 
      return _objs; 
     } 
     set { _objs= value; } 
    } 

Perché è impossibile? Facciamo la stessa cosa in Java:

private List<Obj> objs; 
    public List<Obj> getListObjs() 
    { 
     ... 
     // Recursion 
     return getListObjs(); 
    } 
+0

Non c'è modo di farlo. –

+0

perché creare un esempio in java (a proposito, mi sembra un codice C# valido)? Non sarebbe la stessa logica applicabile in C#? – Default

+0

Le sequenze getter/setter in C# non sono qualcosa che si vede in molte lingue, quindi alcuni principianti potrebbero non capire perché si verifica la ricorsione. Quindi ho pensato che sarebbe stato interessante mostrare cosa effettivamente fa in un modo più standard per scrivere un getter. –

3

No, non c'è modo di farlo senza un campo di supporto. Non correlato alla domanda ma correlato alla situazione. In generale non dovresti esporre un setter per una collezione ma solo un getter. Se hai un setter, esponi molto spesso lo stato interno dell'oggetto, che dovrebbe essere tenuto nascosto.

0

si dovrebbe utilizzare campo privato per memorizzare Elenco di Objs. Non è possibile ottenere dati dal metodo get del metodo get ... :) è una ricorsione.

private List<Obj> _objs; 
public List<Obj> Objs 
{ 
    get { 
    if (_objs== null) 
    { 
     _objs = new List<Obj>(); 
    } 
    if (_objs.Count < 1) 
    { 
     _objs.Add(new Obj()); 
    } 
    return _objs; 
} 
    set { _objs= value; } 
} 
1

La vostra proprietà si riferisce a se stesso nella definizione della parte get della proprietà. Questo è illegale in quanto causerebbe il getter finire in un ciclo infinito. Hai una proprietà auto-implementata (il tuo primo esempio) o una proprietà con un backing field (che viene generato automaticamente dal compilatore per le proprietà auto-implementate). È necessario aggiungere un campo (preferibilmente privato) come backing store per la proprietà:

private List<Obj> objs; 

public List<Obj> Objs 
{ 
    get 
    { 
     if (objs == null) 
     { 
      objs = new List<Obj>(); 
     } 
     if (objs.Count < 1) 
     { 
      objs.Add(new Obj()); 
     } 
     return objs; 
    } 
    set { objs = value; } 
} 
0

No, non proprio.

Nel codice, quando si controlla per if (Objs == null) - si utilizza in modo efficace il metodo get in cui ci si trova attualmente. Quindi chiamate Objs { get; }, ed è per questo che è sempre ricorsivo.

Ricordare che le proprietà automatiche (get; set;) sono in realtà solo una scorciatoia per avere un backing field e metodi get e set separati. Senza che la magia, il codice sarebbe simile a questa:

private List<Obj> _objs; 
public List<Obj> GetObjs() { return _objs; } 
public void SetObjs(List<Objs> objs) { _objs = objs; } 

Quello che stai veramente implementa nel tuo post è questo - notate come GetObjs() chiama se stesso più volte. Quindi, per ogni volta che si chiama, alla fine porterà a chiamarsi di nuovo. E ancora, e ancora una volta .:

public List<Obj> GetObjs() { 
    if (GetObjs() == null) 
    { 
     SetObjs(new List<Obj>()); 
    } 
    if (GetObjs().Count < 1) 
    { 
     GetObjs().Add(new Obj()); 
    } 
    return GetObjs(); 
} 
0
private List<Obj> objs = new List<Obj>() { new Obj() }; 
public List<Obj> Objs { get { return objs; } } 

o se si desidera proteggere da qualcuno di rimuovere l'ultimo Obj

private List<Obj> objs = new List<Obj>(); 
public List<Obj> Objs 
{ 
    get 
    { 
     if (objs.Count == 0) objs.Add(new Obj()); 
     return objs; 
    } 
} 

Quale sarebbe lo scopo di un set di pubblico?