2010-09-15 8 views
7

C'è qualche modo in C# per contrassegnare una proprietà come deterministica?Determinismo proprietà

La ragione per cui chiedo è che spesso mi ritrovo a dichiarare una variabile locale e a leggere una proprietà al suo interno, invece di accedere alla proprietà più volte.

Esiste un modo per decorare la proprietà come deterministica, in modo che il compilatore possa quindi ottimizzare più accessi a tale proprietà? Sto indovinando in un tale scenario che la classe avrebbe bisogno di essere immutabile e decorata come tale.

È qualcosa che esiste anche o sto stringendo le cannucce?

risposta

7

Se la proprietà è semplice, come una proprietà implicita:

public int X { get; set; } 

o leggere da una variabile locale:

public int X { get { return _x; } } 

poi il compilatore di ottimizzare il codice in modo che non v'è alcuna differenza tra accedere alla proprietà più volte e inserire la proprietà in una variabile e accedervi.

Ho verificato questo confrontando 100 milioni di iterazioni di accesso a una proprietà dieci volte e copiando la proprietà su una variabile e l'accesso dieci volte, e non c'è alcuna differenza misurabile.

Generalmente le proprietà devono essere leggerissime, in modo da non dover attendere elaborazioni pesanti ogni volta che le si accede.Se il valore per la proprietà è costoso, la classe deve memorizzare il valore internamente in cache in modo che la lettura della proprietà renda la prima operazione costosa (modello di caricamento lazy).

Se una proprietà è costosa da ottenere ogni volta, non dovrebbe essere una proprietà, ma un metodo getter.

+0

+1 - Solo una domanda: se il compilatore esegue comunque questa ottimizzazione, come considererebbe le modifiche all'oggetto su oggetti non immutabili, indipendentemente dal fatto che fossero dello stesso thread o meno? È possibile che tu abbia appena convalidato che la proprietà ottiene su un semplice costo di proprietà una quantità estremamente piccola, nel qual caso dovrei smettere di essere anale a riguardo? :) –

+0

@ Whit Whitfield: Quando il codice è ottimizzato, la proprietà semplice verrà internata. La lettura della proprietà in realtà non chiama un getter di proprietà per restituire il valore, ma ottiene direttamente il valore, proprio come se si stesse accedendo a una variabile pubblica nella classe. Nel codice C# si ottiene l'astrazione e l'isolamento che si desidera nel codice OOP, ma nel codice compilato si ottiene la velocità delle variabili pubbliche. :) – Guffa

+0

grazie - lo accetterò perché quel commento che hai lì è il bit che mi dà la comprensione che stavo cercando quando ho posto la domanda. –

0

A meno che il campo di supporto della vostra proprietà sia readonly, come avete intenzione di tenere conto dei problemi di threading?

5

In C# non è presente alcun meccanismo che consenta di introdurre getter di proprietà const, ovvero getter che non modificano lo stato dell'oggetto.

La documentazione di Microsoft si limita a raccomandare not to introduce any side-effects nei tuoi getter:

Si tratta di uno stile di programmazione male per cambiare lo stato dell'oggetto utilizzando la funzione di accesso get. Ad esempio, la seguente accessor produce l'effetto collaterale della modifica dello stato dell'oggetto ogni volta che si accede al campo numerico.

private int number; 
public int Number 
{ 
    get 
    { 
     return number++; // Don't do this 
    } 
} 

Come menzionato da Daren, un altro aspetto da considerare è il multi-threading (a meno che l'oggetto è veramente immutabile). Cosa accadrebbe se un altro thread modificasse lo stato dell'oggetto in modo che il getter restituisse un valore diverso nella seconda chiamata? Non esiste un modo semplice per il compilatore di fornire garanzie, ad es. nello scenario di seguito:

class List 
{ 
    IList data; 

    // called several times on thread A 
    // property has no side-effects 
    public int Count { get data.Length; } 

    // called several times on thread B 
    public void Add(object o) 
    { 
     data.Add(o); 
    } 
} 
+0

DateTime.Ora è una proprietà che non cambia stato, ma modifica il valore in ogni caso. Molte altre proprietà riflettono lo stato che può essere modificato con altri mezzi oltre al get setter. –

+0

@Albin Sunnanbo: 'DateTime.Now' non è un buon esempio qui perché è statico e restituisce * un nuovo tipo di valore. Non c'è stato né valore cambiato. Il fatto è che l'OP vuole avere un meccanismo che garantisca che le successive chiamate alla stessa proprietà (almeno in un ambiente a thread singolo) producano lo stesso risultato. –

+0

+1, questo ottiene un voto, sicuramente, ma la cosa che mi chiedo davvero è, se hai seguito le raccomandazioni, c'è un modo per costringere il compilatore a rendersi conto che più proprietà ottiene restituirà lo stesso valore, e quindi compilarli come se si stesse dichiarando prima una variabile locale se si utilizza lo stesso valore di proprietà più volte nello stesso ambito. –

2

Immagino che stai cercando readonly, però io non sono sicuro di come la performance è confrontato a una variabile locale. Ed è applicabile solo ai campi, non alle proprietà.

Oltre a readonly non implica determinismo.

private readonly List<string> fixedList = new List<string>(); 

significa semplicemente che l'oggetto fixedList non può essere sostituito, ma il contenuto può ancora essere modificato.

Problemi correlati