2016-04-22 16 views
12

Was ist der Unterschied zwischen einer Eigenschaft mit einem weggelassenen Setter und einer Eigenschaft mit einem privaten Setter?Ausgelassener Setter gegen privaten Setter?

public string Foo { get; private set; } 

vs

public string Foo { get; } 
+5

Einfach: Eine Eigenschaft mit einem weggelassenen Setter ** hat keinen Setter **. Sie können die Eigenschaft nicht außerhalb der Eigenschaftsdeklaration oder eines Konstruktors neu zuweisen. – BoltClock

+3

Wie kommt diese Frage upvotes? Ich dachte, das war trivial ... – Alex

+3

Duplikatsalarm: http: //stackoverflow.com/questions/3847832/understanding-privi-setters, http://stackoverflow.com/questions/4948816/getters-setters-and-properties- Best-Practices-Java-vs-C-Sharp – Tushar

Antwort

19

In C# 6, get; sind nur Eigenschaften nur vom Konstrukteur einstellbar. Von überall her ist es schreibgeschützt.

Eine Eigenschaft mit einer private set; kann von überall in dieser Klasse eingestellt werden.

+0

Ich sehe. Ich frage mich, warum es die Funktionalität gibt, weggelassene Setter zu haben. Was wäre der Grund, eine Eigenschaft nur durch den Konstruktor, sondern durch Methoden innerhalb der Klasse zu deklarieren? – Fred

+0

Um zu verhindern, dass diese Eigenschaft versehentlich innerhalb dieser Methode gesetzt wird? –

7

Von außerhalb der Klasse, wird es nichts ändern, wenn Sie diese Syntax verwenden:

public string Foo { get; } 

Aber Sie werden aktualisieren Lage sein Foo nicht innerhalb die Klasse, außer im Konstruktor, um dies zu tun, benötigen Sie die private Setter:

public string Foo { get; private set; } 
+1

* Sie können Foo innerhalb der Klasse nicht aktualisieren * Falsch. Sie können es nur im Konstruktor festlegen. –

+0

@PatrickHofman danke für den Kommentar, das wusste ich vorher nicht! –

+0

Es ist interessant, dass jede Antwort diesen bestimmten Teil falsch hat, und immer noch upvotes, während meine darauf hingewiesen, dass von Anfang an und hat keine Abstimmung gewonnen ... –

3

Eine Eigenschaft mit einem ausgelassenen Setter kann nur überall gelesen werden, außer dem Klassenkonstruktor - einschließlich innerhalb der Klasse.

Eine Eigenschaft mit einem privaten Setter ist nur extern lesbar (selbst für Unterklassen), aber intern beschreibbar.

3

Der private Setter ist - nun - eine private Set-Methode, die Sie nur innerhalb Ihrer Klasse verwenden können.

Die entfällt Setter macht die Eigenschaft readonly. Sie können den Wert dieser Eigenschaft nur in Ihren Konstruktoren oder über eine statische Initialisierung festlegen.

5

Der Unterschied ist, dass der generierte Code ein readonly-Feld im zweiten Fall erzeugt, und offensichtlich wird die Eigenschaft keinen Setter haben.

Lassen Sie uns ein konkretes Beispiel tun:

public class Test 
{ 
    public Test(string name) { Name = name; } 
    public string Name { get; private set; } 
} 

Der Compiler kompiliert diese wie folgt aus:

public class Test 
{ 
    private string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
     private set { <Name>k__BackingField = value; } 
    } 
} 

Wie Sie der Compiler automatisch erkennen kann, hat der Code neu geschrieben für die eine dahinter liegende Feld haben Eigentum. Der Feldname wird dieser kryptische Name sein, der legal ist, aber nicht C#, was bedeutet, dass Sie niemals C# -Code schreiben können, der mit einem solchen automatisch erzeugten Member in Konflikt gerät.

Grundsätzlich ist automatische Eigenschaften in C# nur syntaktische Zucker für eine Eigenschaft mit einem Backing-Feld, die eigentliche Eigenschaft kompiliert haben noch ein Backing-Feld, müssen Sie nur nicht explizit schreiben.

Wie Sie sehen können, wurde der Konstruktor automatisch neu geschrieben, um direkt in das Feld zu schreiben. Beachten Sie, dass dies überall in dieser Klasse erfolgt, in die die Eigenschaft geschrieben wird, da sowieso keine Möglichkeit besteht, dass ein benutzerdefinierter Code dazwischen liegt.

Jetzt wollen wir den Setter aus dem Eigentum entfernen und sehen, was passiert:

public class Test 
{ 
    private readonly string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
    } 
} 

Beachten Sie, dass das Feld jetzt nur lesbar ist, und wieder, offensichtlich die Setter hat sich von der Eigenschaft als gut gegangen.

Also das jetzt eigentlich der beste Weg ist, einfache Typen mit wahr Nur-Lese-Eigenschaften zu schaffen, ist nicht nur die Eigenschaft selbst nicht beschreibbar, sondern das dahinter liegendes Feld auch nur lesbar ist Sinn sind Sie jetzt besser gerüstet leicht schreiben unveränderliche Typen.

+0

Interessant, ich denke, das gilt auch für statische schreibgeschützte Eigenschaften (dh wenn es nur ein Auto-Getter deklariert) –

+0

Ja, 'static' spielt in dieser Hinsicht keine Rolle –

+0

Ich habe nicht versucht zu sehen, was passiert ist mit diesem Fall (entweder Instanz oder private Eigenschaften mit nur einem 'Get;'). Daher deklariere ich nicht manuell mehr "readonly" -Felder; P (es sei denn, ich würde sie nicht kapseln müssen, aber der Zugriff auf Klassenfelder ohne Verkapselung ist immer noch eine schlechte Kodierungspraxis). –