it-swarm.com.de

Sollten Sie private Immobilien machen?

private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

Ich habe einige Leute gesehen, die Immobilien für jedes einzelne Mitglied machen, ob privat oder nicht ... macht das irgendeinen Sinn? Ich konnte sehen, dass es in 1% der Fälle sinnvoll ist, wenn Sie den Zugriff auf das Mitglied in der Klasse steuern möchten, in der es enthalten ist. Wenn Sie nicht für jedes Mitglied Eigenschaften verwenden, führt dies zu Inkonsistenzen und zur Überprüfung, ob das Element vorhanden ist Mitglied hat Zugriff oder nicht (da Sie im Bereich der Klasse Zugriff auf beide haben).

19
fordeka

Kurze Antwort: Ja , wenn Bedarf besteht. Verwenden Sie andernfalls einen Auto-Implemented Property Getter und Setter wie private string Whatever { get; set;}

  • Dies ist sehr praktisch, wenn Sie einen Close-Domain-Ansatz verwenden .
  • Es ist auch praktisch, wenn beim Einstellen des Werts eine spezifische Logik überprüft werden soll

Hier finden Sie eine vollständige Beschreibung, wann Sie private Setter verwenden würden: Verwendung der C # -Eigenschaft .

17
Yusubov

Einige gute Antworten hier bereits, aber ich denke, die meisten von ihnen verpassen einen Punkt Ihrer Frage:

Ich habe einige Leute gesehen, die Immobilien für jedes einzelne Mitglied machen, ob privat oder nicht ... macht das irgendeinen Sinn?

Ich denke, dies ist im Voraus selten für jedes einzelne Mitglied erforderlich. Beginnen mit

 private string Whatever;

Wenn Sie später zu einem Punkt kommen, an dem Sie eine Kapselung oder einen bedingten Haltepunkt für dieses bestimmte Mitglied benötigen, können Sie ihn dennoch durch eine Eigenschaft mit demselben Namen ersetzen. in den meisten Fällen ohne den Code zu ändern, der Whatever verwendet. Aber Vorsicht, es gibt subtile Unterschiede, siehe Brian Rasmussens Antwort in this SO post (Link auch von Emmad Kareem, +1).

12
Doc Brown

Einer der größten Vorteile dieses Ansatzes besteht darin, dass Sie die Kontrolle über erhalten, wenn sich Ihre Variablen ändern .

Folgendes berücksichtigen.
Sie debuggen ein großes Projekt. Eine bestimmte Methode löst eine Ausnahme aus. Sie setzen einen Haltepunkt und stellen fest, dass eine bestimmte Mitgliedsvariable einen falschen Wert hat. Angenommen, Ihr Code stützt sich sehr stark auf diese Variable, und Sie finden Hunderte von Schreibverwendungen ( Spaghetti-Szenario). Sie können also nicht herausfinden, welche dieser Verwendungen einen schlechten Wert zugewiesen haben.
Wenn der Code Multithreading ist, kann das Debuggen zu einem echten Albtraum werden.

Mit property können Sie einen Haltepunkt in einem Setter setzen . In Kombination mit einer Bedingung kann es in einem einzigen Durchgang festgenagelt werden.

VC++ hat Daten-Haltepunkte , ist jedoch nur für nicht verwalteten Code verfügbar.

7
bytebuster

Wenn Sie keine Eigenschaft verwenden, können Sie auch ein Feld zum Speichern variabler Daten verwenden. Eigenschaften und Felder weisen erhebliche Unterschiede auf. Die meisten dieser Unterschiede werden gefunden Felder vs. Eigenschaften . Ich schlage vor, Sie studieren die Unterschiede und treffen dann Ihre Wahl entsprechend Ihren Anwendungsanforderungen. Beachten Sie jedoch, dass die Verwendung von Feldern anstelle von Eigenschaften aufgrund ihrer Art und ihres Mangels nicht die übliche OO Praxis ist.

1
NoChance

Private Eigenschaften können sehr nützlich sein, um das Verhalten von Dingen zu kapseln, die in Ihrer Klasse enthalten sind. Nur weil sie privat sind, heißt das nicht, dass Sie den syntaktischen Zucker, den Ihnen die Eigenschaften bieten, nicht nutzen sollten.


Das gegebene Beispiel ist jedoch schlecht. Boilerplate Property Getter und Setter wie diese sind fast immer eine schlechte Idee. Wenn Sie C # 3.0 oder höher verwenden, ist Auto Properties eine viel bessere Idee:

private string Whatever { get; set; };

Dies ist kürzer, sauberer und viel besser lesbar. Tatsächlich ist es kaum länger als nur die Deklaration der Hintergrundvariablen.

Am wichtigsten ist jedoch, dass Auto-Eigenschaften jederzeit in vollständige Eigenschaften konvertiert werden können, ohne die Semantik des restlichen Programms zu ändern! Wenn Sie also eine Validierung oder Fehlerbehandlung hinzufügen müssen, können Sie dies problemlos tun.


So wie es ist, fand ich es immer schade, dass Sie keine schreibgeschützte Eigenschaft haben konnten, um zu erzwingen, dass nur in den Wert im Konstruktor geschrieben werden kann (I bevorzugen unveränderliche Typen ), aber this wurde in C # 6.0 hinzugefügt als "Auto-Property Initializers", mit dem Sie Folgendes tun können:

private string Whatever { get; } = ...;

oder

private string Whatever { get; };

zusammen mit

    Whatever = ...;

im Konstruktor.

1
Mark Booth

Dies ist für private Eigenschaften nicht unbedingt erforderlich, ermöglicht jedoch das Ändern der Art und Weise, wie die Eigenschaft den zugrunde liegenden Wert erhält/festlegt, ohne die Art und Weise zu ändern, in der auf sie zugegriffen wird.

Ändern Sie beispielsweise, wie der zugrunde liegende Wert festgelegt wird:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}
0
Bernard

Ja

Ich persönlich verwende dies als Caching-Mechanismus, und wir könnten es Caching auf Eigenschaftsebene nennen.

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

Jetzt verwende ich an anderen Stellen in meiner Klasse die Eigenschaft Users anstelle des Felds users.

Eine andere mögliche Situation könnte sein, wenn Sie eine Logik in einem Feld implementieren möchten, jedoch zentral in einer Klasse. Auf diese Weise können Sie sowohl eine GetFoo() -Methode als auch eine Foo -Eigenschaft für das foo -Feld erstellen.

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}
0
Saeed Neamati

Noch etwas zu beachten:

Die tatsächlichen Eigenschaften sind ein Implementierungsdetail. Eines der Ziele von OOP ist es, zu versuchen, die Offenlegung von Implementierungsdetails zu minimieren, wo dies praktikabel ist.

Der Grund dafür ist, dass Sie weitaus mehr Kontrolle haben, wenn Sie die Eigenschaften ausblenden und sie nur durch Getter und Setter verfügbar machen. Beispielsweise kann Ihr Getter seine Eingabe überprüfen und verhindern, dass die Eigenschaft in einen ungültigen Zustand versetzt wird. Wenn die Möglichkeit, den Wert zu ändern, zeitkritisch ist, kann der Setter auch davor schützen. Der Getter kann, sollte es aus irgendeinem Grund teuer sein, den tatsächlichen Wert zu erhalten, eine verzögerte Initialisierung und/oder Zwischenspeicherung durchführen.

Wenn Getter und Setter freigelegt und die Eigenschaften ausgeblendet werden, benötigen Sie manchmal überhaupt keine Eigenschaft. Ihr Getter kann den Wert beim Aufruf berechnen oder die Aufgabe an einen anderen Ort delegieren oder alles, was es ermöglicht, die Spezifikation zu erfüllen. Was an Ihrer Klasse wichtig ist, sind die Informationen, auf die Sie zugreifen können, und nicht, wie diese Informationen intern dargestellt werden.

Wenn es keine negativen Konsequenzen gibt, wenn etwas außerhalb der Klasse direkt auf eine Immobilie zugreifen kann, sollten Sie sie einfach öffentlich machen. Nach meiner Erfahrung sind solche Fälle jedoch relativ selten.

0
GordonM

Ich weiß, dass dies eine alte Frage ist und alles @ Yusubov sagte ist korrekt, aber in Bezug auf seinen zweiten Aufzählungspunkt über spezifische Logik = im Setter, und da ich niemanden gesehen habe, der dies ausdrücklich erwähnt, wäre ein perfektes Beispiel, wenn Ihre Klasse die Schnittstelle INotifyPropertyChanged implementiert .

Dies wird eine Tonne in [~ # ~] wcf [~ # ~] und Silverlight verwendet, wodurch Sie wissen = wenn sich eine bestimmte Eigenschaft über die Logik in ihrem Setter wie in der folgenden Klasse geändert hat:

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
0
Code Maverick