Proprietà Getter viene eseguito senza che nessuno definendolo
Domanda
sto lavorando in .net 3.5. Ho una classe "A", che ha una pila e una proprietà getter, che, quando viene chiamato, rimuove il primo elemento della pila e recupera quello successivo.
Dopo l'inizializzazione della classe, ho visto che il getter funziona senza essere stato chiamato, e rimuove l'elemento in cima alla pila, dando così mi cattivi risultati. Un punto di interruzione nella getter non ha mostrato nessuno che lo attraversa.
Quando cambio la proprietà a una funzione, lo stack viene restituito ok.
Sarei felice se qualcuno potrebbe spiegare il motivo per cui è così.
Questa è la classe semplificata:
public class A
{
private Stack<string> Urls;
public A(string title, string[] array)
{
Urls = new Stack<string>();
foreach (string s in array)
{
Urls.Push(s);
}
}
public string Url
{
get { return Urls.Peek(); }
}
public string NextUrl
{
get{
if (Urls.Count > 1)
{ Urls.Pop(); }
return Urls.Peek();
};
}
}
Soluzione
In primo luogo, fare una funzione di accesso di proprietà modificare lo stato è generalmente una cattiva idea. La maggior parte si dovrebbe fare è pigramente inizializzare qualcosa -. O, eventualmente, dare un valore volatile (come DateTime.Now
fa)
In secondo luogo, probabilmente stai vedendo questo se si sta eseguendo nel debugger - si accede a proprietà, mentre si sta passando attraverso il codice. Che probabilmente spiega perché il punto di interruzione non veniva colpito, anche.
Altri suggerimenti
Urls.Pop();
vuole essere
return Urls.Pop();
in quanto restituisce il valore di e rimuove dall'elenco, allo stesso tempo
In realtà dopo aver ri-letto la tua domanda, sembra che è perché il debugger valuta le proprietà. Se si esegue l'applicazione senza il debugger si ottiene lo stesso problema?
Questa è una cattiva progettazione credo. Un accesso get non dovrebbe mutare l'oggetto in un modo che provoca risultati diversi per le chiamate successive.
IMO, il problema qui è avere una proprietà che ha non evidenti effetti collaterali; questo dovrebbe essere un metodo:
public string GetNextUrl() { /* */ }
In caso contrario, le cose brutte accadono ovunque (il debugger, data-binding, ecc). Non date per scontato che qualcuno legge solo una proprietà di una volta.
L'unico uso ragionevole di effetti collaterali nelle proprietà è cose come lazy-loading, inizializzazione differita, ecc Deve comunque segnalare lo stesso valore quando chiamato in sequenza senza altre chiamate mutanti evidenti.