2016-05-08 12 views
5

Zum Beispiel, ich habe eine unveränderliche ArtUnveränderliche Typen mit Objektinitialisierer Syntax

class Contact 
{ 
    // Read-only properties. 
    public string Name { get; } 
    public string Address { get; } 
} 

Und ich hoffe, dass ich Objektinitialisierer Syntax verwenden kann einen Kontakt erstellen

Contact a = new Contact { Name = "John", Address = "23 Tennis RD" }; 

Aber ich kann es nicht. Gibt es eine Möglichkeit, in diesem Fall die mächtige Objektinitialisierersyntax zu verwenden?

Antwort

4

würde die nächste Sache, ein Konstruktor mit optionalen Parametern sein:

class Contact 
{ 
    public string Name { get; } 
    public string Address { get; } 
    public Contact(string name = null, string address = null) { 
     Name = name; 
     Address = address; 
    } 
} 

Dann können Sie es mit Parameternamen nennen:

new Contact(
    name: "John", 
    address: "23 Tennis RD" 
) 

Die Syntax von einem Objekt initializer ist etwas anders, aber es ist genauso lesbar; und IMO, der Unterschied ist eine gute Sache, weil Konstruktor-Parameter dazu neigen, unveränderliche Eigenschaften vorzuschlagen. Und Sie können die Parameter in beliebiger Reihenfolge angeben, oder lassen Sie einige aus, so ist es genauso leistungsfähig wie Objektinitialisierersyntax.

Dies erfordert einige zusätzlichen Code (Definieren des Konstruktors, Zuweisen aller Eigenschaften), also ist es mehr Arbeit als Objektinitialisierersyntax. Aber nicht zu schrecklich, und der Wert von unveränderlichen Objekten ist es wert.

(Für was es wert ist, 7 C# immutable "record types" die viel einfachere Syntax bekommen können diese möglicherweise nicht in die endgültige Version machen, aber sie klingen ziemlich cool..)

0

Objektinitialisierer erstellt zuerst das Objekt und dann Eigenschaftswerte. Es braucht Setter.

Es ist kurzerhand für:

Contact a = new Contact(); 
a.Name = "John"; 
a.Address = "23 Tennis RD"; 

Ein Nur-Lese-Feld nicht, es ist gesetzt Werte haben kann, sobald das Objekt konstruiert wurde. Um diese Klasse unveränderlich haben, müssen Sie einen Konstruktor erstellen, diese Werte zu nehmen:

class Contact // Immutable class 
{ 
    // Read-only properties. 
    public string Name { get; } 
    public string Address { get; } 
    public Contact(string name, string address) 
    { 
     this.Name = name; 
     this.Address = address; 
    } 
} 
+0

ich Setter muss - nein es tut nicht! Es erfordert Schreibzugriff auf das Feld oder die Property. Im Falle einer Eigenschaft benötigt es tatsächlich einen Setter. Im Falle eines Felds kann es nicht nur statisch oder schreibgeschützt sein. –

+0

Korrekt. Grund, warum ich sagte: "dann Eigenschaftswerte setzen, erfordert Setter". Selbst bei einem öffentlichen Setter würde, wenn das Hintergrundfeld nur gelesen wurde, der Versuch, darauf zu schreiben, nicht einmal kompiliert werden. –

1

Nö, können Sie es nicht verwenden, mit Nur-Lese-Eigenschaften.
Hier sind die verschiedenen Eigenschaften und Feldtypen im Vergleich.

public class sometype { 
    public int readonlyProp{ 
     get; 
    } 
    public int normalProp { 
     get; 
     set; 
    } 

    public const int constField = 3; 
    public readonly int readonlyField = 3; 
    public int normalField = 3; 

    public void test() { 
     sometype test = new sometype() { readonlyProp = 3}; //  Doesn't work -> Property or indexer is readonly 
     sometype test1 = new sometype() { normalProp = 3 }; //  ok 
     sometype test2 = new sometype() { constField = 3 }; //  Doesn't work -> Static field or property 
     sometype test3 = new sometype() { readonlyField = 3 }; // Doesn't work -> readonly field 
     sometype test4 = new sometype() { normalField = 3 }; //  ok 
    } 
} 

Es ist wichtig zu verstehen, dass const-Felder als statisch betrachtet werden und somit keine Instanzmitglieder sind. Und da der Objektinitialisierer für Instanzmitglieder verwendet wird, funktioniert dies nicht.

Verwandte Themen