2016-05-08 11 views
5

Na przykład, mam niezmienna typuniezmienne typy z obiektu inicjatora składni

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

I mam nadzieję, że mogę używać składni inicjatora obiektu, aby utworzyć kontakt

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

Ale nie mogę. Czy w tym przypadku możliwe jest użycie potężnej składni inicjalizatora obiektu?

Odpowiedz

4

Najbliżej byłoby konstruktor z opcjonalnymi parametrami:

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

Następnie można wywołać go z nazw parametrów:

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

Składnia jest nieco różni się od inicjowania obiektu, ale to tak samo czytelny; i IMO, różnica jest dobra, ponieważ parametry konstruktora sugerują niezmienne właściwości. I możesz określić parametry w dowolnej kolejności lub zostawić je poza domem, więc jest tak samo potężne, jak składnia inicjatora obiektu.

Wymaga to dodatkowego kodu (definiującego konstruktora, przypisującego wszystkie właściwości), więc jest to więcej pracy niż składnia inicjatora obiektu. Ale nie za straszne, a wartość niezmiennych obiektów jest tego warta.

(Na co warto, C# 7 może dostać immutable "record types" że mają znacznie prostszą składnię To może lub nie może uczynić go do ostatecznej wersji, ale brzmią całkiem fajne.).

0

Inicjator obiektów najpierw skonstruuje obiekt, a następnie ustawi wartości właściwości. Potrzebuje ustawiaczy.

To krótki ręka dla:

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

tylko do odczytu pole nie może mieć to wartości ustawione gdy obiekt został zbudowany. Mieć, że klasa niezmienna, musisz utworzyć konstruktor wziąć te wartości:

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

ja potrzebuje ustawiające - nope to robi nie! Wymaga prawa do zapisu na polu lub propery. W przypadku nieruchomości rzeczywiście potrzebuje settera. W przypadku pola to po prostu nie może być statyczne ani tylko do odczytu. –

+0

Prawidłowo. Powód dla którego powiedziałem: "następnie ustaw wartości właściwości, wymaga Settera". Nawet z publicznym ustawiaczem, jeśli pole zaplecza było tylko do odczytu, próba napisania do niego nie byłaby nawet kompilowana. –

1

Nie, nie można go używać z właściwości tylko do odczytu.
Oto różne właściwości i typy pól w porównaniu.

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

Należy zrozumieć, że pola const są uważane za statyczne, a zatem nie są elementami instancji. A ponieważ inicjator obiektu jest używany dla członków instancji, to nie działa.