2010-09-15 25 views
7

Czy jest jakiś sposób w C#, aby oznaczyć właściwość jako deterministyczną?Determinizm własności

Powodem, dla którego pytam, jest to, że często znajduję się deklarując zmienną lokalną i czytając właściwość do niej, zamiast wielokrotnie uzyskiwać dostęp do nieruchomości.

Czy istnieje sposób, w jaki mogę udekorować nieruchomość jako deterministyczną, tak aby kompilator mógł zoptymalizować wielokrotne dostępy do tej właściwości? Zgaduję, że w takim scenariuszu klasa musiałaby być niezmienna i tak udekorowana.

Czy to coś, co istnieje, czy też trzymam się kurczowo słomek?

Odpowiedz

7

Jeżeli nieruchomość jest proste, jak własności niejawny:

public int X { get; set; } 

lub czytanie ze zmiennej lokalnej:

public int X { get { return _x; } } 

następnie kompilator zoptymalizować kod tak, że nie ma różnicy pomiędzy wielokrotny dostęp do nieruchomości i umieszczanie nieruchomości w zmiennej i dostęp do niej.

Sprawdziłem to, porównując 100 milionów powtórzeń dostępu do nieruchomości dziesięciokrotnie i kopiując właściwość do zmiennej i uzyskując dostęp do niej dziesięć razy, i nie ma żadnej różnicy mierzalnej.

Ogólnie, właściwości powinny być lekkostrawne, aby nie trzeba było oczekiwać ciężkiego przetwarzania za każdym razem, gdy uzyskujesz do niego dostęp.Jeśli wartość właściwości jest kosztowna, klasa powinna buforować wartość wewnętrznie, tak aby odczyt właściwości wykonywał tylko kosztowną operację po raz pierwszy (leniwy schemat ładowania).

Jeśli nieruchomość jest kosztowna za każdym razem, nie powinna to być właściwość, ale metoda gettera.

+0

+1 - Tylko jedno pytanie - jeśli kompilator mimo to robi tę optymalizację, to w jaki sposób uwzględniłby zmiany obiektu na niezmiennych obiektach - czy to z tego samego wątku, czy nie? Czy to możliwe, że właśnie potwierdziłeś, że własność dostaje się na prostą własność kosztującą bardzo małą sumę, w którym to przypadku powinienem przestać o tym mówić? :) –

+0

@Matt Whitfield: Kiedy kod zostanie zoptymalizowany, prosta właściwość zostanie internowana. Odczytanie właściwości nie wywoła funkcji pobierającej właściwości w celu zwrócenia wartości, ale uzyska wartość bezpośrednio, tak jak w przypadku uzyskiwania dostępu do publicznej zmiennej w klasie. W kodzie C# otrzymujesz abstrakcję i izolację, którą chcesz w kodzie OOP, ale w skompilowanym kodzie dostajesz prędkość zmiennych publicznych. :) – Guffa

+0

dziękuję - mam zamiar to zaakceptować, ponieważ ten komentarz, który tam masz, jest tym, co daje mi zrozumienie, którego szukałem, gdy zadałem to pytanie. –

0

Jeśli nie masz pola wsparcia dla swojej nieruchomości to readonly, w jaki sposób zamierzasz uwzględnić wątki?

5

Nie ma mechanizmu w języku C#, który umożliwia wprowadzanie elementów pobierających właściwości const, tj. Modułów pobierających, które nie zmieniają stanu obiektu.

Dokumentacja Microsoft zaleca not to introduce any side-effects po prostu w swoim pobierające:

To jest zły styl programowania, aby zmienić stan obiektu za pomocą akcesor get. Na przykład następujący akcesor wywołuje efekt uboczny zmiany stanu obiektu za każdym razem, gdy dostęp do pola numeru jest uzyskiwany.

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

Jak wspomniano przez Daren, inny aspekt do rozważenia jest wielowątkowości (chyba, że ​​obiekt jest naprawdę niezmienne). Co jeśli inny wątek zmienił stan obiektu, aby getter zwracał inną wartość w drugim wywołaniu? Kompilator nie ma łatwego sposobu na uzyskanie jakichkolwiek gwarancji, np. w poniższym scenariuszu:

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.Now jest właściwością, która nie zmienia stanu, ale zmienia wartość mimo to. Wiele innych właściwości odzwierciedla stan, który można zmienić za pomocą innych środków, niż tylko ustawiający. –

+0

@Albin Sunnanbo: 'DateTime.Now' nie jest tutaj dobrym przykładem, ponieważ jest statyczny i * zwraca * nowy typ wartości. Nie ma zmienionego stanu ani wartości. Rzecz polega na tym, że OP chce mieć mechanizm gwarantujący, że kolejne wywołania tej samej właściwości (przynajmniej w środowisku jednowątkowym) przyniosą taki sam rezultat. –

+0

+1, to zdecydowanie daje głos, ale naprawdę zastanawiam się, czy zastosowałeś się do zaleceń, czy istnieje jakikolwiek sposób przekonania kompilatora, aby zorientował się, że wiele własności otrzyma taką samą wartość, a zatem kompiluj je tak, jakbyś deklarował najpierw zmienną lokalną, jeśli wielokrotnie używasz tej samej wartości właściwości w tym samym zasięgu. –

2

Chyba szukasz readonly, jednak nie jestem pewien w jaki sposób wyniki są porównywane do zmiennej lokalnej. I dotyczy tylko pól, a nie właściwości.

Poza tym readonly nie oznacza determinizmu.

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

oznacza po prostu, że obiekt fixedList nie może być zastąpiony, ale treść można jeszcze zmienić.