Proprietà C #, perché controllare l’uguaglianza prima dell’assegnazione

Perché vedo le persone implementare proprietà come questa?
A che serve controllare se il valore è uguale al valore corrente?

public double? Price { get { return _price; } set { if (_price == value) return; _price = value; } } 

In questo caso sarebbe discutibile; tuttavia, nel caso in cui vi sia un effetto collaterale associato (tipicamente un evento), evita eventi banali. Per esempio:

 set { if (_price == value) return; _price = value; OnPriceChanged(); // invokes the Price event } 

Ora, se lo facciamo:

 foo.Price = 16; foo.Price = 16; foo.Price = 16; foo.Price = 16; 

non riceviamo 4 eventi; otteniamo al massimo 1 (forse 0 se è già 16).

In esempi più complessi potrebbero esserci validazione, azioni pre-cambiamento e azioni post-cambiamento. Tutti questi possono essere evitati se si sa che non è in realtà un cambiamento.

 set { if (_price == value) return; if(value < 0 || value > MaxPrice) throw new ArgumentOutOfRangeException(); OnPriceChanging(); _price = value; OnPriceChanged(); } 

Questa non è una risposta, di più: è una risposta basata sull’evidenza del reclamo (in un’altra risposta) che è più veloce da controllare che da assegnare. In breve: no, non lo è. Nessuna differenza. Ottengo (per non nullable int ):

 AutoProp: 356ms Field: 356ms BasicProp: 357ms CheckedProp: 356ms 

(con alcune piccole variazioni su serie successive – ma sostanzialmente tutte prendono esattamente lo stesso tempo in ogni arrotondamento ragionevole – quando si fanno qualcosa 500 milioni di volte, possiamo ignorare la differenza di 1ms)

In effetti, se cambiamo in int? Ottengo:

 AutoProp: 714ms Field: 536ms BasicProp: 714ms CheckedProp: 2323ms 

o double? (come nella domanda):

 AutoProp: 535ms Field: 535ms BasicProp: 539ms CheckedProp: 3035ms 

quindi questo non è un aiuto alle prestazioni!

con test

 class Test { static void Main() { var obj = new Test(); Stopwatch watch; const int LOOP = 500000000; watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.AutoProp = 17; } watch.Stop(); Console.WriteLine("AutoProp: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.Field = 17; } watch.Stop(); Console.WriteLine("Field: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.BasicProp = 17; } watch.Stop(); Console.WriteLine("BasicProp: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.CheckedProp = 17; } watch.Stop(); Console.WriteLine("CheckedProp: {0}ms", watch.ElapsedMilliseconds); Console.ReadLine(); } public int AutoProp { get; set; } public int Field; private int basicProp; public int BasicProp { get { return basicProp; } set { basicProp = value; } } private int checkedProp; public int CheckedProp { get { return checkedProp; } set { if (value != checkedProp) checkedProp = value; } } } 

Supponiamo di non gestire alcun evento correlato al cambiamento. Non penso che il confronto sia più veloce dell’assegnazione. Dipende dal tipo di dati. Supponiamo che tu abbia una stringa, il Confronto è molto più lungo nel caso peggiore di un semplice compito in cui il membro cambia semplicemente il riferimento al riferimento della nuova stringa. Quindi la mia ipotesi è che sia meglio in questo caso assegnare subito. Nel caso di tipi di dati semplici non ha un impatto reale.

Ad esempio, non è necessario riassegnare lo stesso valore. La sua esecuzione più veloce per confrontare i valori. per quanto ne so