Jak mogę uzyskać dostęp do zmiennej zapasowej właściwości zaimplementowanej automatycznie?

79

W przeszłości deklarowaliśmy takie właściwości:

public class MyClass
{
    private int _age;

    public int Age
    {
          get{ return _age;  }
          set{ _age = value; }
    }
}

Teraz możemy:

public class MyClass
{
    public int Age {get; set;} 
}

Moje pytanie brzmi: w jaki sposób mogę uzyskać dostęp do prywatnej zmiennej, która jest tworzona automatycznie przy użyciu tej notacji?

Wolałbym raczej uzyskać dostęp do zmiennej prywatnej, a nie do publicznego akcesora „Wiek”. Czy istnieje domyślna notacja dostępu do zmiennej prywatnej, czy po prostu nie jest to możliwe?

publiczne statyczne
źródło
10
Jaka jest różnica w tym przypadku dostępu prywatnego i publicznego? Myślę, że najlepszą praktyką jest uzyskiwanie dostępu do publicznego akcesora nawet z poziomu logiki w klasie deklarującej. Jeśli kiedykolwiek dodasz jakąś logikę do akcesora, nie będziesz musiał zmieniać całego kodu.
Eric Schoonover,
@ spoon16 Czy możesz podać przykład dodawania logiki do akcesorium i konieczności zmiany całego kodu? Naprawdę nie rozumiałem tej części.
Ogen

Odpowiedzi:

92

Celem nowych właściwości automatycznych jest zmniejszenie ilości kodu standardowego, który trzeba napisać, gdy mamy tylko prostą właściwość, która nie wymaga żadnej specjalnej logiki w get lub zestawie.

Jeśli chcesz uzyskać dostęp do prywatnego członka, którego używają te właściwości, jest to zwykle z kilku powodów:

  • Potrzebujesz czegoś więcej niż tylko prostego pobierania / ustawiania - w takim przypadku powinieneś po prostu unikać używania właściwości automatycznych dla tego elementu członkowskiego.
  • Chcesz uniknąć uderzenia w wydajność przechodzenia przez get lub set i po prostu użyj członka bezpośrednio - w tym przypadku byłbym zaskoczony, gdyby naprawdę był hit. Proste elementy członkowskie get / set są bardzo łatwe do wbudowania, aw moich (co prawda ograniczonych) testach nie znalazłem różnicy między używaniem właściwości automatycznych a bezpośrednim dostępem do elementu członkowskiego.
  • Chcesz mieć tylko publiczny dostęp do odczytu (tj. Po prostu „pobierz”), a klasa zapisuje bezpośrednio do członka - w takim przypadku możesz użyć prywatnego zestawu w swojej właściwości automatycznej. to znaczy

    public class MyClass
    {
        public int Age {get; private set;} 
    }

Zwykle obejmuje to większość powodów, dla których chcesz bezpośrednio przejść do pola zapasowego używanego przez właściwości automatyczne.

Wilka
źródło
To prawda - redukują kod melonika, a ja również reklamuję, że zmniejszają to, co musisz przetestować. Niektórzy mogą twierdzić, że musisz przetestować ręczne pobieranie / ustawianie, ale nie z właściwościami automatycznymi, ponieważ możesz ufać strukturze.
Daniel Auger
3
Przykładowy kod jest tutaj nieprawidłowy. Powinna to być klasa publiczna MyClass {public int Age {get; zestaw prywatny;}} Zgadzam się z tą odpowiedzią. Nie możesz uzyskać dostępu do pola prywatnego, a jeśli musisz, to przede wszystkim nie powinieneś używać właściwości automatycznych.
hwiechers
hwiechers, dzięki za to - miałem tę edycję, ale próbując naprawić formatowanie musiałem ponownie nacisnąć wklej i skasować zły blok kodu. No!
Wilka
Powszechnie używane w obiektach POCO
RobS,
23

Korzystanie z właściwości automatycznych oznacza, że ​​nie potrzebujesz żadnej logiki pobierania / ustawiania właściwości, dlatego prywatna zmienna zapasowa jest niepotrzebna.

Nie używaj właściwości automatycznych, jeśli masz jakąś złożoną logikę w swojej klasie. Po prostu idź private int _agei normalne pobierające / ustawiające, jak zwykle.

IMO, właściwości automatyczne są bardziej odpowiednie do szybkiego wdrażania obiektów jednorazowego użytku lub tymczasowych kapsułek danych, takich jak:

public class TempMessage {
    public int FromID { get; set; }
    public int ToID { get; set; }
    public string Message { get; set; }
}

Gdzie nie potrzebujesz dużo logiki.

chakrit
źródło
Dlaczego dodanie złożonej logiki do klasy miałoby wpływać na to, czy użyto automatycznych właściwości w tej klasie?
Eric Schoonover,
Bardziej spójna sprawa ... jeśli masz złożoną logikę, będziesz chciał uzyskać do niej dostęp z prywatnej zmiennej bazowej zgodnie z praktykami OO .. a jeśli używasz właściwości automatycznych, to ... wystąpią niespójności w dostępie do tych właściwości . ponieważ niektóre będą miały prefiks podkreślenia, a inne nie.
chakrit
12

Ta składnia jest powszechnie nazywana „cukrem składniowym”, co oznacza, że ​​kompilator przyjmuje tę składnię i tłumaczy ją na coś innego. W twoim przykładzie kompilator wygeneruje kod, który wygląda mniej więcej tak:

[CompilerGenerated]
private int <Age>k_BackingField;

public int Age
{
   [CompilerGenerated]
   get
   {
      return this.<Age>k_BackingField;
   }
   [CompilerGenerated]
   set
   {
      this.<Age>k_BackingField = value;
   }

Nawet wiedząc o tym wszystkim, prawdopodobnie można uzyskać bezpośredni dostęp do pola zapasowego, ale w ten sposób udaremnia się cel używania właściwości automatycznych. Mówię tutaj prawdopodobnie, ponieważ wtedy polegasz na szczegółach implementacji, które mogą ulec zmianie w dowolnym momencie w przyszłej wersji kompilatora C #.

Scott Dorman
źródło
10

Za kulisami następuje wstrzyknięcie prywatnej zmiennej składowej z prefiksem <> k__AutomaticallyGeneratedPropertyField #

Od C # 3.0 Automatyczne właściwości wyjaśnione

Chociaż możliwe jest bezpośrednie użycie tego prywatnego członka, jest to bardzo hakerskie i niepotrzebne.

macbirdie
źródło
7

Nie powinieneś i jest bardzo mało prawdopodobne, że będziesz musiał. Jeśli potrzebujesz dostępu do nieruchomości, po prostu użyj własności publicznej (np. This.Age). Nie ma nic specjalnego w prywatnym polu wspierającym własność publiczną, używanie go zamiast własności jest po prostu przesądem.

Klin
źródło
1
Zawsze się zastanawiałem, jaki jest sens automatycznych właściwości. Jeśli nie masz specjalnej logiki w swoich getterach i seterach, dlaczego w ogóle je masz?
Matthew Lock
4
@MatthewLock elastyczność. Dzięki bezpośredniemu dostępowi do pola jesteś zamknięty w tym projekcie, chyba że zmienisz cały kod klienta w tym samym czasie. Ale jeśli zdecydujesz się zmienić ją z „pseudo-pola” na obliczoną właściwość, lub jeśli zdecydujesz się dodać potwierdzenia i sprawdzenia ustawiacza lub tego, co masz, możesz to zrobić w sposób przejrzysty. Jest to jeszcze bardziej przydatne, jeśli piszesz kod biblioteki, w której nie możesz kontrolować całego kodu klienta.
Wedge
2

Nie możesz, jest to funkcja języka w przeciwieństwie do funkcji IDE. Szczerze mówiąc, wolałbym wtedy IDE dodać prywatną zmienną za Ciebie. Zgadzam się, że to trochę dziwne, że klasa musi wewnętrznie używać publicznego punktu wejścia, aby uzyskać dostęp do własnych zmiennych. Dlatego sam nie korzystam zbyt często z tej nowej funkcji.

Kłopotliwe
źródło