2009-06-26 9 views
12

Mój projekt zawiera dużą liczbę klas z właściwościami, których pole zaplecza jest oznaczone jako przeczytane, ponieważ są one ustawione tylko w konstrukcji. Ze względu na styl, lubię używać auto-właściwości, ponieważ eliminuje to wiele kodu standardowego i zachęca do korzystania z elementu własności, a nie z pola zaplecza. Jednak przy korzystaniu z auto-własności tracę "tylko do odczytu" z mojego pola podkładu. Rozumiem, że kompilator/runtime jest w stanie skorzystać z pewnych ulepszeń wydajności, gdy pole jest zaznaczone w ten sposób, więc chciałbym, aby móc oznaczyć moje auto właściwość jako tylko do odczytu, coś takiego:Czy można wymusić automatyczną właściwość, aby użyć pola tylko do odczytu?

[ReadOnly] 
public string LastName { get; } 

a nie

private readonly string _LastName; 
public string LastName 
{ 
    get 
    { 
     return _LastName; 
    } 
} 

Czy jest jakiś mechanizm już dostępny, aby to zrobić? Jeśli nie, czy poprawa wydajności z niestandardowego pola wsparcia jest naprawdę warta przeczytania?

Ujawnienie pola jako publicznego jest inną opcją, jak sądzę, po prostu wydaje się błędne wystawienie pola w ten sposób. tj

public readonly string LastName; 
+1

Zgadzam się, wydaje się błędne, aby odsłonić publiczne pole tylko do odczytu. Jeśli kiedykolwiek zajdzie potrzeba zmiany na właściwość później, zmiana naruszy zgodność. –

+2

Jak prawidłowo odpowiedziały odpowiedzi, nie, nie ma sposobu, aby to teraz zrobić. Jest to najczęściej żądana funkcja i zdecydowanie znajduje się wysoko na liście możliwych nowych funkcji hipotetycznych przyszłych wersji tego języka. Osobiście chciałbym mieć cały zestaw powiązanych funkcji, które zachęcają do programowania w niezmienionym stylu; to byłby tylko jeden z nich. –

Odpowiedz

13

nie boję, ale można to zrobić:

public string LastName { get; private set; } 

Nie tak dobry jak readonly, ale nie jest tak źle.

+0

Czy "readonly string Foo {get {return" bar ";} set;}' i 'string Foo {get {return" bar ";}}" odpowiednik? –

4

Nie, nie jest i gdyby była to funkcja bezużyteczna bez znaczącego poprawiania.

Pole tylko do odczytu może być weryfikowalne tylko z konstruktora. Własność zaimplementowaną automatycznie można ustawić tylko z wygenerowanego narzędzia ustawiającego. Są to niezgodne wymagania i wygenerują kod, który nie może być zweryfikowany.

Tak, możesz potencjalnie uczynić kompilator wystarczająco inteligentnym, aby zignorować ustawiacza i przejść bezpośrednio do pola zaplecza w konstruktorze. Ale w samym seterze wciąż nie można zweryfikować. Kompilator musiałby pominąć go w wygenerowanym kodzie, ponieważ spowoduje powstanie prawdziwie tylko do odczytu właściwości. Wywołuje to inną sprzeczność, ponieważ nadal musiałbyś wykonać polecenie przypisania do nieruchomości.

Foo() { 
    SomeProperty = "somevalue"; 
} 

W tym przypadku kod wygląda tak, jakby wywoływał osobę ustawiającą w usłudze. Ale tak naprawdę nie można ustawić wywołania, ponieważ musi on zostać pominięty w ostatecznym kodzie.

EDIT

ten nie mówi, że nie można zrobić. Może, ale wymagałoby to trochę pracy z C#.

W szczególności będą musiały zapewnić sposób ustawienia pola zaplecza nieruchomości, która nie może mieć ustawiacza. Można to zrobić na kilka sposobów.

  • Daj użytkownikom dostęp do pola poparcie auto realizowany własności
  • Pozwól składnię stylu seter chociaż nie ma seter i niech kompilator przełożyć go do dostępu do pola pod maską
  • Invent trochę nowej składni

Nie twierdzę, że któraś z tych opcji to dobra opcja, ale tylko po to, by umożliwić działanie tego typu funkcji.

+0

Potrzebna jest do tego alternatywna składnia, ale bardzo bym chciała, aby była możliwa. Dodam z tym odpowiedź ... –

+0

@Ja zgodziłem się, zmieniłem swoją odpowiedź, aby powiedzieć "znaczące poprawki" – JaredPar

+0

+1, aby przejść do długości, aby wyjaśnić, dlaczego. Dość ciekawe. – jasper

1

Preferuję prawdziwe pole podkładowe readonly, ponieważ gwarantuje to, że nie zmieniam tego pola po zakończeniu budowy.

1

Nie i nie. Nie ma sposobu, aby to zrobić i nie ma żadnego zwiększenia wydajności dla tylko do odczytu pól.

+0

Zrozumiałem, że "statyczna readonly" pozwala JIT dokonać pewnych optymalizacji, takich jak nigdy nie wykonywanie kopii wartości. – JulianR

+0

@JulianR - Z tego, co wiem, nie ma żadnych korzyści związanych z wydajnością. Zobacz http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c –

+2

Nie chodzi o wydajność, chodzi o bezpieczne kodowanie. –

8

Nie, niestety nie ma sposobu, aby to zrobić. Osobiście są dwie rzeczy, których, moim zdaniem, brakuje w automatycznych implementacjach właściwości w C# - domyślna wartość (która jak sądzę będzie w VB10) i tylko do odczytu właściwości, które można ustawić tylko w konstruktorze. Innymi słowy, chciałbym być w stanie to zrobić:

public class Foo 
{ 
    public string Tag { get; internal set; } = "Default value"; 

    // The "readonly" would imply "private" as it could only 
    // be set from a constructor in the same class 
    public int Value { get; readonly set; } 

    public Foo() 
    { 
     // Valid to set property here, but nowhere else 
     Value = 20; 
    } 
} 

Jak wspomniano Jared, oznaczałoby to zmianę połączeń kompilator ustawiająca własności do prostych zadań terenowych i upewniając się, że wystąpił tylko w konstruktorze.

Ułatwi to pisanie typów niezmiennych. Niestety sytuacja nie poprawi się w C# 4. Miejmy nadzieję, że otrzymamy coś takiego dla C# 5 ...

+0

Czy w międzyczasie preferowany jest jeden nad drugim? Wygląda na to, że zarówno autopromosowość bezterminowa, jak i implementacja tylko pola podkładowego zapewniają niezmienną implementację. Czy to po prostu kwestia stylu? – JadeMason

+5

Ja osobiście trzymam się pola z czystym zapleczem, chyba że jest to kod wyrzucony. Podoba mi się, że to * właściwie * niezmienne, nawet jeśli przypadkowo spróbuję ustawić to w moim własnym typie. –

+0

Eugh! Jak seter może być tylko do odczytu? Być może public readonly int Wartość {get; zestaw; } –

3

Od C# 6.0 odpowiedź brzmi "tak". Twój przykład może być napisany jak poniżej, a kompilator automatycznie generuje pole tylko do odczytu za właściwością. Nazywa się to automatyczną własnością typu getter.

public string LastName { get; } 

Od https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

Getter tylko auto-właściwości są dostępne w obu strukturach i klasa deklaracji , ale są szczególnie ważne ze względu na elemencie praktyce wytyczną najlepszą że elemencie być niezmienna . Zamiast sześciu lub mniej linii potrzebnych do zadeklarowania właściwości tylko do odczytu i zainicjowania go przed C# 6.0, teraz wystarczy tylko deklaracja jednowierszowa i przypisanie z konstruktora. Tak więc deklaracja niezmiennych struktur jest teraz nie tylko prawidłowym wzorcem programowania dla struktur, ale także prostszym wzorcem - bardzo cenioną zmianą z poprzedniej składni, gdzie prawidłowe kodowanie wymagało więcej wysiłku.

Powiązane problemy