webentwicklung-frage-antwort-db.com.de

Gibt es Gründe, private Eigenschaften in C # zu verwenden?

Ich habe gerade festgestellt, dass das C # Eigenschaftskonstrukt auch mit dem Modifikator private access verwendet werden kann:

private string Password { get; set; }

Obwohl dies technisch interessant ist, kann ich mir nicht vorstellen, wann ich es verwenden würde, da ein privates Feld sogar weniger Zeremonie beinhaltet :

private string _password;

und ich kann mir nicht vorstellen, wann ich jemals in der Lage sein müsste, intern zu bekommen aber nicht zu setzen oder zu setzen aber nicht get ein privates Feld:

private string Password { get; }

oder

private string Password { set; }

aber vielleicht gibt es einen Anwendungsfall mit verschachtelten/geerbten Klassen oder vielleicht, wo ein get/set Logik enthalten könnte, anstatt nur den Wert der Eigenschaft zurückzugeben, obwohl ich dazu neige, Eigenschaften streng einfach zu halten und lassen Sie explizite Methoden eine beliebige Logik ausführen, z GetEncodedPassword().

Verwendet jemand private Eigenschaften in C # aus irgendeinem Grund oder ist es nur eines dieser technisch möglichen und doch selten verwendeten Codekonstrukte?

Nachtrag

Schöne Antworten, ich habe diese Verwendungen für Privateigentum ausgesucht:

  • wenn private Felder faul geladen werden müssen
  • wenn private Felder zusätzliche Logik benötigen oder berechnete Werte sind
  • da private felder schwierig zu debuggen sein können
  • um "sich selbst einen Vertrag vorzulegen"
  • internes Konvertieren/Vereinfachen einer exponierten Eigenschaft im Rahmen der Serialisierung
  • umbrechen globaler Variablen, die in Ihrer Klasse verwendet werden sollen
201
Edward Tanguay

Ich verwende sie, wenn ich einen Wert zwischenspeichern muss und ihn faul laden möchte.

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

        return _password;
    }
}
179
Shaun Bowe

Dies wird in meinem Code hauptsächlich für die langsame Initialisierung verwendet, wie andere bereits erwähnt haben.

Ein weiterer Grund für private Eigenschaften über Felder ist, dass private Eigenschaften viel einfacher zu debuggen sind als private Felder. Ich möchte häufig wissen, dass "dieses Feld unerwartet gesetzt wird; wer ist der erste Anrufer, der dieses Feld festlegt?" und es ist viel einfacher, wenn Sie einfach einen Haltepunkt auf den Setter setzen und auf "Los" klicken. Sie können sich dort anmelden. Sie können dort Leistungskennzahlen eingeben. Sie können Konsistenzprüfungen durchführen, die im Debugbuild ausgeführt werden. 

Im Grunde kommt es darauf an: Code ist weitaus leistungsfähiger als Daten . Jede Technik, mit der ich den Code schreiben kann, den ich brauche, ist eine gute. In Feldern können Sie keinen Code schreiben, Eigenschaften jedoch. 

117
Eric Lippert

vielleicht gibt es einen Anwendungsfall mit verschachtelten/vererbten Klassen oder vielleicht, wo ein get/set Logik enthalten kann, anstatt nur den Wert der Eigenschaft zurückzugeben

Ich persönlich benutze das auch, wenn ich keine Logik für den Getter oder Setter einer Immobilie benötige. Die Verwendung einer Eigenschaft, auch einer privaten, hilft, den Code für die Zukunft zu sichern, sodass Sie die Logik später einem Getter hinzufügen können, falls dies erforderlich ist.

Wenn ich der Meinung bin, dass eine Eigenschaft möglicherweise eine zusätzliche Logik erfordert, wickle ich sie manchmal in eine private Eigenschaft ein, anstatt ein Feld zu verwenden, nur damit ich meinen Code später nicht ändern muss.


In einem halbbezogenen Fall (wenn auch anders als in Ihrer Frage) verwende ich sehr häufig private Setter in öffentlichen Gebäuden:

public string Password 
{
    get; 
    private set;
}

Dadurch erhalten Sie einen öffentlichen Getter, der Setzer bleibt jedoch privat.

37
Reed Copsey

Faule Initialisierung ist ein Ort, an dem sie ordentlich sein können, z.

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;

Dann können Sie Folgendes schreiben: this.MyType an Stelle von this.mytype.Value und kapseln Sie die Tatsache ein, dass es faul an einem einzigen Ort instanziiert wird.

Eine Sache, die schade ist, ist, dass C # das Unterstützungsfeld für die Eigenschaft nicht unterstützt (d. H. Es in der Eigenschaftsdefinition deklariert), um es vollständig zu verbergen und sicherzustellen, dass nur über die Eigenschaft auf dieses Feld zugegriffen werden kann.

19
Greg Beech

Eine gute Verwendung für private get-only-Eigenschaften sind berechnete Werte. Ich hatte mehrmals Eigenschaften, die privat gelesen werden können und nur eine Berechnung über andere Felder in meinem Typ ausführen. Es ist keine Methode wert und für andere Klassen nicht interessant, also ist es das Privateigentum.

17
JaredPar

Die einzige Verwendung, die ich mir vorstellen kann

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}
12
Lukasz Madon

Eigenschaften und Felder sind nicht eins zu eins. Eine Eigenschaft handelt von der Schnittstelle einer Klasse (unabhängig davon, ob sie über ihre öffentliche oder interne Schnittstelle spricht), während sich in einem Feld die Implementierung der Klasse befindet. Eigenschaften sollten nicht als eine Möglichkeit zum Ausblenden von Feldern verstanden werden, sondern als Möglichkeit, die Absicht und den Zweck der Klasse offenzulegen. 

So wie Sie Eigenschaften verwenden, um Ihren Verbrauchern einen Vertrag über das, was Ihre Klasse ausmacht, vorzulegen, können Sie sich auch aus sehr ähnlichen Gründen einen Vertrag vorlegen. Ja, ich benutze private Immobilien, wenn es sinnvoll ist. Manchmal kann eine private Eigenschaft Implementierungsdetails verbergen, wie z. B. das langsame Laden, die Tatsache, dass eine Eigenschaft tatsächlich aus mehreren Feldern und Aspekten besteht oder dass eine Eigenschaft bei jedem Aufruf virtuell instanziiert werden muss (think DateTime.Now). Es gibt auf jeden Fall Zeiten, in denen es sinnvoll ist, dies auch im Backend der Klasse durchzusetzen.

8
Matt Greer

Ich verwende sie in der Serialisierung, mit Dingen wie DataContractSerializer oder protobuf-net, die diese Verwendung unterstützen (XmlSerializer nicht). Dies ist nützlich, wenn Sie ein Objekt im Rahmen der Serialisierung vereinfachen müssen:

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}
7
Marc Gravell

Eine Sache, die ich ständig mache, ist "globale" Variablen/Cache in HttpContext.Current zu speichern

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
Earlz

Ich verwende private Eigenschaften, um den Code für den Zugriff auf häufig verwendete Sub-Eigenschaften zu reduzieren.

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

Dies ist nützlich, wenn es viele Sub-Eigenschaften gibt.

5

Ich benutze sie ab und zu. Sie können das Debuggen erleichtern, wenn Sie einen Haltepunkt in die Eigenschaft einfügen oder eine Protokollierungsanweisung hinzufügen.

Kann auch nützlich sein, wenn Sie später den Datentyp auf irgendeine Weise ändern müssen oder Reflektion verwenden müssen.

5
Hans Olsson

Es ist üblich, Mitglieder nur mit get/set-Methoden zu ändern, auch mit privaten. Nun, die Logik dahinter ist, dass Sie wissen, dass sich das Get/Set immer auf eine bestimmte Weise verhält (z. B. das Auslösen von Ereignissen), was nicht sinnvoll erscheint, da diese nicht in das Eigenschaftsschema aufgenommen werden ... aber alte Gewohnheiten sterben schwer.

2
corsiKa

Es ist absolut sinnvoll, wenn mit der Eigenschaftssatz oder -logik Logik verbunden ist (denken Sie an eine langsame Initialisierung) und die Eigenschaft wird an einigen Stellen der Klasse verwendet.

Wenn es nur ein gerades Hintergrundfeld ist? Nichts ist ein guter Grund.

2
Marc

Ich weiß, dass diese Frage sehr alt ist, aber die folgenden Informationen waren in keiner der aktuellen Antworten enthalten.

Ich kann mir nicht vorstellen, wann ich jemals in der Lage sein müsste, intern zu bekommen, aber nicht zu setzen

Wenn Sie Ihre Abhängigkeiten injizieren, möchten Sie möglicherweise einen Getter für eine Eigenschaft und keinen Setter, da dies eine schreibgeschützte Eigenschaft bedeuten würde. Mit anderen Worten, die Eigenschaft kann nur im Konstruktor festgelegt und von keinem anderen Code innerhalb der Klasse geändert werden.

Außerdem gibt Visual Studio Professional Informationen zu einer Eigenschaft und nicht zu einem Feld aus, sodass Sie leichter sehen können, welches Feld verwendet wird.

 PorpField 

0
Guy

Einige exotischere Verwendungen expliziter Felder umfassen:

  • sie müssen refoder outmit dem Wert verwenden - möglicherweise, weil es sich um einen Interlockedname__-Zähler handelt
  • es ist beabsichtigt um ein grundlegendes Layout zum Beispiel auf einem structmit explizitem Layout darzustellen (vielleicht um einen C++ - Dump zuzuordnen, oder unsafename__-Code)
  • in der Vergangenheit wurde der Typ mit BinaryFormattermit automatischer Feldbehandlung verwendet (durch die Umstellung auf Auto-Requisiten werden die Namen geändert, wodurch der Serializer unterbrochen wird).
0
Marc Gravell

Nun, da niemand erwähnt wurde, können Sie damit Daten validieren oder Variablen sperren.

  • Validierung

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

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

    Hinweis: Beim Sperren einer Referenz sperren Sie nicht den Zugriff auf Mitglieder des referenzierten Objekts.

Faule Referenz: Beim Lazy-Loading müssen Sie es eventuell asynchron machen, für die heutzutage AsyncLazy vorhanden ist. Wenn Sie ältere Versionen des Visual Studio SDK 2015 verwenden oder nicht verwenden, können Sie auch AsyncExs AsyncLazy verwenden.