2012-04-24 6 views
7

Betrachten Sie den folgenden Code ein:Was ist der Zweck dieses Ansatzes für Zugriffsmodifikatoren?

private string _text = null; 
    private string[] _values = null; 

    public string Text { get { return _text; } } 
    public string[] Values { get { return _values; } } 

Was dies nicht erreichen, dass die öffentlichen Member allein mit würde das nicht?

+7

Beachten Sie, dass Sie * sehr, sehr vorsichtig * sein sollten, wenn Sie ein Array als schreibgeschützte Eigenschaft einer Klasse verfügbar machen. ** Der Array-Verweis ist schreibgeschützt, der Array-Inhalt jedoch nicht. ** Der Benutzer dieser Klasse kann den Inhalt des Arrays nach Belieben mutieren. Wenn das nicht erwünscht ist, geben Sie stattdessen eine 'ReadOnlyCollection ', keine 'string []' zurück. –

+1

Erics detaillierte Gedanken zu diesem Thema: http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-consided-somewhatful.aspx – SolutionYogi

Antwort

10

Wenn Sie Eigenschaften anstelle von öffentlichen Feldern verwenden, blenden Sie die Implementierung aus.

Wenn Sie an einem bestimmten Punkt ändern müssen, was die Eigenschaften Text und Werte zurückgeben, können Sie das Verhalten ändern, ohne die API der Klasse zu ändern.

Darüber hinaus beschränkt dieses Idiom den externen Zugriff auf die exponierten Daten als schreibgeschützt.

+2

Umformuliert die Frage des Lesezugriffs, hoffe dass das weniger zweideutig ist. Danke an @AdamHouldsworth! –

5

Mit diesem Code können externe Entitäten Ihre Werte lesen, während Ihr Code das Backing-Feld intern ändern kann.

Sie können Kurz Hand, dass Auto-Eigenschaften mit:

public string Text { get; private set; } 
public string[] Values { get; private set; } 

Mit einem öffentlichen Bereich, würden Sie nicht in der Lage sein, gegen äußere Veränderung zu schützen und interne Modifikation zugleich unterstützen.

Selbst wenn Sie ein Feld extern beschreibbar machen möchten, würde ich dennoch vorschlagen, das Ding in eine Eigenschaft zu kapseln - Sie wissen nie, ob Sie intern etwas unterstützen müssen, ohne den externen Vertrag zu brechen (benutzerdefinierter Code im set/get) gibt Ihnen Raum, dies zu tun).

Ganz zu schweigen von den meisten Datenbindung Frameworks nicht Felder sehen, nur Eigenschaften.

2

Die _text und _values können nur innerhalb der Klasse festgelegt werden, für die sie definiert sind, aber ihre Werte sind über die Eigenschaften zugänglich.

6

Es ist Wert nur lesbar zu machen, obwohl ich eher geneigt, würde es wie folgt zu schreiben:

public string Text { get; private set;} 
public string[] Values { get; private set; } 
+3

Dies würde nur die Werte nur zu Sachen außerhalb der Klasse lesen lassen. –

+0

@AdamHouldsworth Ich stimme nicht zu. – asawyer

+2

Nur klärend, weil Wörter wie readonly herumwerfen mit dem Schlüsselwort 'readonly' verwechselt werden könnten. –

2

In Ihrem Beispiel seine Eigenschaften machen als nur lesen, aber es gibt auch andere Verwendungen.

public string Text { get { return _text; } } 

Wenn Sie eine Operation intern auf dem return_text tun wollen und es dann wieder gegen proeperty Text könnte man so etwas.

public string Text { get { return _text.ToUpper(); } } 

Dies ist Feld Encapsulation

Encapsulation wird manchmal als erste Säule oder Prinzip der objektorientierten Programmierung. Nach dem Prinzip der Kapselung, eine Klasse oder Struktur kann angeben, wie zugänglich jeder von seine Mitglieder Code außerhalb der Klasse oder Struktur ist. Methoden und Variablen, die nicht von außerhalb der Klasse oder Assembly verwendet werden sollen, können ausgeblendet werden, um die Möglichkeit von Codierungsfehlern oder schädlichen Angriffen auf zu begrenzen.

Betrachten Sie das folgende Beispiel:

// private field 
    private DateTime date; 


    // Public property exposes date field safely. 
    public DateTime Date 
    { 
     get 
     { 
      return date; 
     } 
     set 
     { 
      // Set some reasonable boundaries for likely birth dates. 
      if (value.Year > 1900 && value.Year <= DateTime.Today.Year) 
      { 
       date = value; 
      } 
      else 
       throw new ArgumentOutOfRangeException(); 
     } 

    } 

In diesem Beispiel gibt es ein privates Feld ist date die Date öffentlich durch Eigentum ausgesetzt ist. Wenn Sie jetzt die Grenze für das Datum festlegen möchten, können Sie den festgelegten Teil der Eigenschaft sehen.