Implementieren einer einfachen Klasse mit automatisch implementierten Eigenschaften
In diesem Beispiel wird gezeigt, wie Sie eine unveränderliche einfache Klasse erstellen, die nur zum Kapseln einer Reihe automatisch implementierter Eigenschaften dient. Verwenden Sie diese Konstruktart anstelle einer Struktur, wenn Sie eine Verweistypsemantik verwenden müssen.
Für das Erstellen einer unveränderlichen Eigenschaft gibt es die folgenden Möglichkeiten:
- Deklarieren Sie nur die get-Zugriffsmethode. Auf diese Weise wird die Eigenschaft überall (außer im Konstruktor des Typs) unveränderlich.
- Deklarieren Sie eine init-Zugriffsmethode anstelle einer
set
-Zugriffsmethode. Die Eigenschaft kann dann nur im Konstruktor oder mithilfe eines Objektinitialisierers festgelegt werden. - Deklarieren Sie die set-Zugriffsmethode als privat. Die Eigenschaft kann im Typ festgelegt werden, ist aber für Consumer unveränderlich.
Sie können den required
-Modifizierer zur Eigenschaftendeklaration hinzufügen, um Aufrufer zu zwingen, die Eigenschaft als Teil der Initialisierung eines neuen Objekts festzulegen.
Das folgende Beispiel zeigt, wie eine Eigenschaft, die nur eine get-Zugriffsmethode aufweist, sich von einer Eigenschaft mit „get“ und „private set“ unterscheidet.
class Contact
{
public string Name { get; }
public string Address { get; private set; }
public Contact(string contactName, string contactAddress)
{
// Both properties are accessible in the constructor.
Name = contactName;
Address = contactAddress;
}
// Name isn't assignable here. This will generate a compile error.
//public void ChangeName(string newName) => Name = newName;
// Address is assignable here.
public void ChangeAddress(string newAddress) => Address = newAddress;
}
Beispiel
Das folgende Beispiel zeigt zwei Möglichkeiten zum Implementieren einer unveränderlichen Klasse, die automatisch Eigenschaften implementiert hat. Mit beiden Möglichkeiten wird jeweils eine der Eigenschaften mit einer privaten set
und eine der Eigenschaft mit einer get
deklariert. Die erste Klasse verwendet einen Konstruktor nur zum Initialisieren der Eigenschaften, und die zweite Klasse verwendet eine statische Factorymethode, die einen Konstruktor aufruft.
// This class is immutable. After an object is created,
// it cannot be modified from outside the class. It uses a
// constructor to initialize its properties.
class Contact
{
// Read-only property.
public string Name { get; }
// Read-write property with a private set accessor.
public string Address { get; private set; }
// Public constructor.
public Contact(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
}
// This class is immutable. After an object is created,
// it cannot be modified from outside the class. It uses a
// static method and private constructor to initialize its properties.
public class Contact2
{
// Read-write property with a private set accessor.
public string Name { get; private set; }
// Read-only property.
public string Address { get; }
// Private constructor.
private Contact2(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
// Public factory method.
public static Contact2 CreateContact(string name, string address)
{
return new Contact2(name, address);
}
}
public class Program
{
static void Main()
{
// Some simple data sources.
string[] names = ["Terry Adams","Fadi Fakhouri", "Hanying Feng",
"Cesar Garcia", "Debra Garcia"];
string[] addresses = ["123 Main St.", "345 Cypress Ave.", "678 1st Ave",
"12 108th St.", "89 E. 42nd St."];
// Simple query to demonstrate object creation in select clause.
// Create Contact objects by using a constructor.
var query1 = from i in Enumerable.Range(0, 5)
select new Contact(names[i], addresses[i]);
// List elements cannot be modified by client code.
var list = query1.ToList();
foreach (var contact in list)
{
Console.WriteLine("{0}, {1}", contact.Name, contact.Address);
}
// Create Contact2 objects by using a static factory method.
var query2 = from i in Enumerable.Range(0, 5)
select Contact2.CreateContact(names[i], addresses[i]);
// Console output is identical to query1.
var list2 = query2.ToList();
// List elements cannot be modified by client code.
// CS0272:
// list2[0].Name = "Eugene Zabokritski";
}
}
/* Output:
Terry Adams, 123 Main St.
Fadi Fakhouri, 345 Cypress Ave.
Hanying Feng, 678 1st Ave
Cesar Garcia, 12 108th St.
Debra Garcia, 89 E. 42nd St.
*/
Der Compiler erstellt Sicherungsfelder für jede automatisch implementierte Eigenschaft. Es ist nicht möglich, im Quellcode direkt auf die Felder zuzugreifen.