2016-05-08 79 views
5

Per esempio, ho un tipo immutabiletipi immutabili con la sintassi di inizializzazione degli oggetti

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

E spero di poter utilizzare la sintassi di inizializzazione degli oggetti per creare un contatto

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

ma non ci riesco. In questo caso, è possibile utilizzare la potente sintassi di inizializzazione dell'oggetto?

risposta

4

La cosa più vicina sarebbe un costruttore con parametri opzionali:

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

Poi si può chiamare con i nomi dei parametri:

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

La sintassi è leggermente diverso da un inizializzatore oggetto, ma è altrettanto leggibile; e IMO, la differenza è una buona cosa, perché i parametri del costruttore tendono a suggerire proprietà immutabili. E puoi specificare i parametri in qualsiasi ordine, o lasciarne alcuni, quindi è altrettanto potente della sintassi di inizializzatore di oggetti.

Ciò richiede un codice aggiuntivo (definizione del costruttore, assegnazione di tutte le proprietà), quindi è più utile della sintassi di inizializzazione dell'oggetto. Ma non troppo terribile, e vale la pena il valore di oggetti immutabili.

(per quello che vale, C# 7 può ottenere immutable "record types" che hanno sintassi molto più semplice Questi possono o non possono farne la versione finale, ma il suono piuttosto fresco..)

0

Inizializzatore oggetto per prima cosa costruisce l'oggetto, quindi imposta i valori delle proprietà. Ha bisogno di setter.

È breve mano per:

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

Un campo di sola lettura non può avere sia valori impostati una volta che l'oggetto è stato costruito. Per avere quella classe immutabile, avrete bisogno di creare un costruttore di prendere quei valori:

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

I ha bisogno setter - no lo fa non! Richiede accesso in scrittura sul campo o proprietà. Nel caso di una proprietà ha effettivamente bisogno di un setter. Nel caso di un campo non può essere statico o solo in lettura. –

+0

corretto. Motivo per cui ho detto: "quindi imposta i valori delle proprietà, richiede setter". Anche con un setter pubblico, se il backing field era in sola lettura, provare a scriverlo non sarebbe nemmeno stato compilato. –

1

No, non è possibile utilizzarlo con proprietà di sola lettura.
Ecco i diversi tipi di proprietà e campi nel confronto.

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 
    } 
} 

È importante capire che i campi const sono considerati statici e quindi non sono membri di istanze. E poiché l'inizializzatore dell'oggetto viene utilizzato per i membri di esempio, questo non funziona.