Czy są jakieś powody, aby używać własności prywatnych W C#?

Właśnie zdałem sobie sprawę, że konstrukcja właściwości C# może być również używana z modyfikatorem dostępu private :

private string Password { get; set; }

Chociaż jest to technicznie interesujące, nie wyobrażam sobie, kiedy bym go użył, ponieważ prywatne pole obejmuje nawet mniej ceremonii :

private string _password;

I nie wyobrażam sobie, kiedy kiedykolwiek będę musiała być w stanie get but not set lub set but not get prywatny pole:

private string Password { get; }

Lub

private string Password { set; }

Ale być może istnieje przypadek użycia z zagnieżdżonymi / dziedziczonymi klasami lub być może get/set może zawierać logikę zamiast po prostu zwracać wartość właściwości, chociaż chciałbym zachować właściwości ściśle proste i pozwolić jawnym metodom wykonywać dowolną logikę, np. GetEncodedPassword().

Czy ktoś używa prywatnych właściwości w C# z jakiegokolwiek powodu, czy jest to tylko jedna z tych technicznie-możliwych-ale-rzadko-używanych-w-rzeczywistym-kodzie konstrukcje?

Dodatek

Ładne odpowiedzi, czytając je opisałem te zastosowania dla własności prywatnych:

  • gdy pola prywatne muszą być leniwie ładowane
  • gdy pola prywatne wymagają dodatkowej logiki lub są wartościami obliczonymi
  • ponieważ debugowanie prywatnych pól może być trudne]} W celu "zaprezentowania sobie umowy"]} W ten sposób można łatwo przekształcić i uprościć obiekt jako część serializacji.]}
  • owijanie zmienne globalne do użycia wewnątrz klasy
Author: Edward Tanguay, 2010-07-22

14 answers

Używam ich, jeśli muszę buforować wartość i chcę ją leniwie załadować.

private string _password;
private string Password
{
    get
    {
        if (_password == null)
        {
            _password = CallExpensiveOperation();
        }

        return _password;
    }
}
 163
Author: Shaun Bowe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 20:12:38

Podstawowym zastosowaniem tego w moim kodzie jest leniwa inicjalizacja, jak już inni wspominali.

Innym powodem, dla którego prywatne właściwości są nad polami, jest to, że prywatne właściwości są dużo, dużo łatwiejsze do debugowania niż prywatne pola. Często chcę wiedzieć rzeczy takie jak " to pole jest ustawiane nieoczekiwanie; kto jest pierwszym wywołującym, który ustawia to pole?"jest to o wiele łatwiejsze, jeśli możesz po prostu umieścić punkt przerwania na seterze i nacisnąć go. Możesz tam umieścić logowanie. Możesz umieścić wydajność tam są metryki. Możesz wprowadzić kontrole spójności, które są uruchamiane w kompilacji debugowania.

Zasadniczo sprowadza się to do: kod jest znacznie potężniejszy niż DANE . Każda technika, która pozwala mi napisać kod, którego potrzebuję, jest dobra. Pola nie pozwalają na pisanie w nich kodu, właściwości tak.

 106
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 15:16:34

Być może istnieje przypadek użycia z klasami zagnieżdżonymi / dziedziczonymi lub być może get / set może zawierać logikę zamiast zwracać wartość właściwości

Osobiście używam tego nawet wtedy, gdy nie potrzebuję logiki na getterze lub setterze właściwości. Korzystanie z właściwości, nawet prywatnej, pomaga zabezpieczyć kod w przyszłości, dzięki czemu można dodać logikę do gettera później, jeśli jest to wymagane.

Jeśli uznam, że nieruchomość może w końcu wymagać dodatkowej logiki, będę czasami zawinąć go do prywatnej własności, zamiast używać pola, tylko po to, żebym nie musiał zmieniać kodu później.


W częściowo powiązanym przypadku (choć innym niż twoje pytanie), bardzo często używam prywatnych seterów na publicznych właściwościach:

public string Password 
{
    get; 
    private set;
}

To daje Ci publiczny getter, ale utrzymuje setera w tajemnicy.

 36
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 14:56:05

Leniwa inicjalizacja to jedno miejsce, w którym mogą być schludne, np.

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);

private MyType MyType { get { return this.mytype.Value; } }

// In C#6, you replace the last line with: private MyType MyType => myType.Value;

Wtedy możesz napisać: this.MyType wszędzie, a nie this.mytype.Value i zawrzeć fakt, że jest on leniwie utworzony w jednym miejscu.

Jedna rzecz, która jest wstydliwa, to to, że C# nie obsługuje przeszukiwania pola zaplecza do właściwości (tj. deklarowania go wewnątrz definicji właściwości), aby całkowicie ją ukryć i upewnić się, że może być dostępna tylko za pośrednictwem właściwości.

 19
Author: Greg Beech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-03 18:39:27

Jednym z dobrych zastosowań dla prywatnych właściwości get only są obliczane wartości. Kilka razy miałem właściwości, które są prywatne readonly i po prostu zrobić obliczenia nad innymi polami w moim typie. To nie jest godne metody i nie interesujące dla innych klas, więc własność prywatna to jest.

 15
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 15:06:12

Jedyne użycie, o którym myślę

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}
 11
Author: Lukasz Madon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 14:59:50

Właściwości i pola nie są pojedynczo. Właściwość dotyczy interfejsu klasy (niezależnie od tego, czy chodzi o jej publiczny czy wewnętrzny Interfejs), podczas gdy pole dotyczy implementacji klasy. Właściwości nie powinny być postrzegane jako sposób na wyeksponowanie pól, powinny być postrzegane jako sposób na wyeksponowanie intencji i celu klasy.

Tak jak używasz właściwości, aby przedstawić konsumentom umowę na to, co stanowi Twoją klasę, możesz również przedstawić umowę na siebie z bardzo podobnych powodów. Więc tak, używam prywatnych nieruchomości, gdy ma to sens. Czasami własność prywatna może ukryć szczegóły implementacji, takie jak leniwe Ładowanie, fakt, że właściwość jest naprawdę konglomeratem kilku pól i aspektów lub że właściwość musi być wirtualnie utworzona przy każdym wywołaniu (think DateTime.Now). Są zdecydowanie momenty, w których sensowne jest egzekwowanie tego nawet na sobie w zapleczu klasy.

 8
Author: Matt Greer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 15:01:45

Używam ich w serializacji, z rzeczami takimi jak DataContractSerializer lub protobuf-net, które obsługują to użycie (XmlSerializer nie). Jest to przydatne, jeśli trzeba uprościć obiekt w ramach serializacji:

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}
 7
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 15:29:10

Jedną rzeczą, którą robię cały czas, jest przechowywanie "globalnych" zmiennych / pamięci podręcznej w HttpContext.Current

private static string SomeValue{
  get{
    if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
      HttpContext.Current.Items["MyClass:SomeValue"]="";
    }
    return HttpContext.Current.Items["MyClass:SomeValue"];
  }
  set{
    HttpContext.Current.Items["MyClass:SomeValue"]=value;
  }
}
 6
Author: Earlz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 15:37:18

Używam ich od czasu do czasu. Mogą one ułatwić debugowanie rzeczy, gdy można łatwo umieścić w punkcie przerwania we właściwości lub można dodać instrukcję logging itp.

Może być również przydatny, jeśli później trzeba zmienić rodzaj danych w jakiś sposób lub jeśli trzeba użyć refleksji.

 5
Author: Hans Olsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 14:55:31

Używam prywatnych właściwości, aby zmniejszyć kod dostępu do sub właściwości, które często są używane.

    private double MonitorResolution
    {
        get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
    }

Jest to przydatne, jeśli istnieje wiele właściwości podrzędnych.

 5
Author: Yohanes Nurcahyo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 10:25:23

Powszechną praktyką jest modyfikowanie tylko członków za pomocą metod get/set, nawet prywatnych. Logika jest taka, że Twój get / set zawsze zachowuje się w określony sposób (na przykład odpalanie zdarzeń), co nie wydaje się mieć sensu, ponieważ nie będą one zawarte w schemacie właściwości... ale stare nawyki umierają ciężko.

 2
Author: corsiKa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 14:57:17

Ma to sens, gdy z właściwością set lub get jest powiązana logika (think lazy initialization) i właściwość jest używana w kilku miejscach w klasie.

Jeśli to tylko proste pole zapasowe? Nic nie przychodzi mi do głowy jako dobry powód.

 2
Author: Marc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 14:58:15

Cóż, jak nikt nie wspomniał, można go użyć do walidacji danych lub do blokowania zmiennych.

  • Walidacja

    string _password;
    string Password
    {
        get { return _password; }
        set
        {
            // Validation logic.
            if (value.Length < 8)
            {
                throw new Exception("Password too short!");
            }
    
            _password = value;
        }
    }
    
  • Blokowanie

    object _lock = new object();
    object _lockedReference;
    object LockedReference
    { 
        get
        {
            lock (_lock)
            {
                return _lockedReference;
            }
        }
        set
        {
            lock (_lock)
            {
                _lockedReference = value;
            }
        }
    }
    

    Uwaga: podczas blokowania odniesienia nie blokuje się dostępu do elementów obiektu odniesienia.

Lazy reference: gdy leniwe ładowanie może skończyć się koniecznością zrobienia tego asynchronicznego, dla którego obecnie istnieje AsyncLazy . Jeśli korzystasz ze starszych wersji niż Visual Studio SDK 2015 lub nie używając go Możesz również użyć asynclazy AsyncEx.

 0
Author: Lucas Martins Juviniano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-25 01:59:52