Właściwości (Przewodnik programowania w języku C#)
Właściwość jest elementem członkowskim, który zapewnia elastyczny mechanizm odczytu, zapisu lub obliczania wartości pola danych. Właściwości są wyświetlane jako elementy członkowskie danych publicznych, ale są implementowane jako specjalne metody nazywane metodami dostępu. Ta funkcja umożliwia obiektom wywołującym łatwe uzyskiwanie dostępu do danych i nadal pomaga promować bezpieczeństwo i elastyczność danych. Składnia właściwości to naturalne rozszerzenie pól. Pole definiuje lokalizację magazynu:
public class Person
{
public string? FirstName;
// Omitted for brevity.
}
Automatycznie zaimplementowane właściwości
Definicja właściwości zawiera deklaracje metody get
i set
, która pobiera i przypisuje wartość tej właściwości:
public class Person
{
public string? FirstName { get; set; }
// Omitted for brevity.
}
W poprzednim przykładzie przedstawiono automatycznie zaimplementowaną właściwość. Kompilator generuje ukryte pole zapasowe dla właściwości . Kompilator implementuje również treść elementów get
i set
metod dostępu. Wszystkie atrybuty są stosowane do automatycznie zaimplementowanej właściwości. Atrybut można zastosować do pola kopii zapasowej wygenerowanego przez kompilator, określając field:
tag atrybutu.
Właściwość można zainicjować na wartość inną niż domyślna, ustawiając wartość po zamykającym nawiasie klamrowym dla właściwości. Możesz preferować początkową wartość FirstName
właściwości jako pusty ciąg, a nie null
. Należy określić to, jak pokazano w poniższym kodzie:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
Właściwości kopii zapasowej pola
W języku C# 13 można dodać walidację lub inną logikę w metodzie dostępu dla właściwości przy użyciu funkcji podglądu słowa kluczowego field
. Słowo field
kluczowe uzyskuje dostęp do syntetyzowanego pola kopii zapasowej kompilatora dla właściwości. Umożliwia pisanie metody dostępu do właściwości bez jawnego deklarowania oddzielnego pola zapasowego.
public class Person
{
public string? FirstName
{
get;
set => field = value.Trim();
}
// Omitted for brevity.
}
Ważne
Słowo field
kluczowe jest funkcją w wersji zapoznawczej w języku C# 13. Musisz użyć platformy .NET 9 i ustawić element <LangVersion>
na preview
w pliku projektu, aby użyć field
kontekstu słowa kluczowego.
Należy zachować ostrożność przy użyciu funkcji słowa kluczowego field
w klasie, która ma pole o nazwie field
. Nowe field
słowo kluczowe cieniuje pole o nazwie field
w zakresie metody dostępu właściwości. Możesz zmienić nazwę zmiennej field
lub użyć tokenu @
, aby odwołać się do identyfikatora field
jako @field
. Aby dowiedzieć się więcej, przeczytaj specyfikację funkcji słowa kluczowego field
.
Wymagane właściwości
W poprzednim przykładzie obiekt wywołujący może utworzyć Person
obiekt wywołujący przy użyciu konstruktora domyślnego bez ustawiania FirstName
właściwości . Właściwość zmieniła typ na ciąg dopuszczalny do wartości null. Począwszy od języka C# 11, można wymagać od wywołujących ustawienia właściwości:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
// Omitted for brevity.
}
Powyższy kod wprowadza dwie zmiany w Person
klasie. FirstName
Najpierw deklaracja właściwości zawiera required
modyfikator. Oznacza to, że każdy kod tworzący nową Person
właściwość musi ustawić tę właściwość przy użyciu inicjatora obiektów. Po drugie, konstruktor, który przyjmuje firstName
parametr, ma System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute atrybut . Ten atrybut informuje kompilator, że ten konstruktor ustawia wszystkie required
elementy członkowskie. Obiekty wywołujące używające tego konstruktora nie są wymagane do ustawiania required
właściwości za pomocą inicjatora obiektu.
Ważne
Nie należy mylić required
z wartością niepustą. Prawidłowe jest ustawienie required
właściwości na null
lub default
. Jeśli typ jest niepusty, taki jak string
w tych przykładach, kompilator wyświetla ostrzeżenie.
var aPerson = new Person("John");
aPerson = new Person{ FirstName = "John"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();
Definicje treści wyrażeń
Metody dostępu do właściwości często składają się z instrukcji jednowierszowych. Metody dostępu przypisują lub zwracają wynik wyrażenia. Te właściwości można zaimplementować jako elementy członkowskie wyrażeń. Definicje treści wyrażeń składają się z tokenu =>
, po którym następuje wyrażenie, które ma zostać przypisane do właściwości lub pobrane z tej właściwości.
Właściwości tylko do odczytu mogą implementować metodę get
dostępu jako składową typu wyrażenie-bodied. Poniższy przykład implementuje właściwość tylko Name
do odczytu jako składową typu wyrażenie-bodied:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public required string FirstName { get; init; }
public required string LastName { get; init; }
public string Name => $"{FirstName} {LastName}";
// Omitted for brevity.
}
Właściwość Name
jest właściwością obliczoną. Nie ma pola tworzenia kopii zapasowej dla elementu Name
. Właściwość oblicza ją za każdym razem.
Kontrola dostępu
W poprzednich przykładach pokazano właściwości odczytu/zapisu. Można również utworzyć właściwości tylko do odczytu lub zapewnić różne ułatwienia dostępu do zestawu i uzyskać metody dostępu. Załóżmy, że klasa Person
powinna włączać tylko zmianę wartości FirstName
właściwości z innych metod w klasie. Można nadać zestaw dostępu dostępu private
zamiast internal
lub public
:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Właściwość FirstName
można odczytać z dowolnego kodu, ale można ją przypisać tylko z kodu w Person
klasie.
Możesz dodać dowolny restrykcyjny modyfikator dostępu do zestawu lub uzyskać metody dostępu. Modyfikator dostępu do poszczególnych metod dostępu musi być bardziej restrykcyjny niż dostęp do właściwości. Powyższy kod jest legalny, ponieważ FirstName
właściwość to public
, ale zestaw metod dostępu to private
. Nie można zadeklarować private
właściwości za pomocą public
metody dostępu. Deklaracje właściwości można również zadeklarować protected
, internal
, protected internal
, lub nawet private
.
Istnieją dwa specjalne modyfikatory dostępu dla set
metod dostępu:
- Akcesorium
set
może miećinit
jako modyfikator dostępu. Taset
metoda dostępu może być wywoływana tylko z inicjatora obiektu lub konstruktorów typu. Jest bardziej restrykcyjny niżprivate
na akcesoriumset
. - Właściwość zaimplementowana automatycznie może zadeklarować metodę
get
dostępu bezset
metody dostępu. W takim przypadku kompilator umożliwiaset
wywoływanie metody dostępu tylko z konstruktorów typu. Jest bardziej restrykcyjny niżinit
akcesorium na akcesoriumset
.
Zmodyfikuj klasę w Person
następujący sposób:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
Powyższy przykład wymaga, aby wywołujący używali konstruktora zawierającego FirstName
parametr . Obiekt wywołujący nie może użyć inicjatorów obiektów do przypisania wartości do właściwości. Aby obsługiwać inicjatory, można ustawić metodę set
init
dostępu, jak pokazano w poniższym kodzie:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Modyfikatory te są często używane z modyfikatorem, aby wymusić właściwą inicjację required
.
Właściwości z polami zapasowymi
Można mieszać koncepcję obliczonej właściwości z polem prywatnym i utworzyć buforowane oceniane właściwości. Na przykład zaktualizuj FullName
właściwość, aby formatowanie ciągu odbywało się przy pierwszym dostępie:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public required string FirstName { get; init; }
public required string LastName { get; init; }
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Ta implementacja działa, ponieważ FirstName
właściwości i LastName
są tylko do odczytu. Użytkownicy mogą zmienić swoje imię i nazwisko. FirstName
Zaktualizowanie właściwości i LastName
w celu zezwolenia na set
metody dostępu wymaga unieważnienia dowolnej wartości buforowanej dla elementu fullName
. Zmodyfikujesz set
FirstName
metody dostępu właściwości i LastName
, aby fullName
pole zostało ponownie obliczone:
public class Person
{
private string? _firstName;
public string? FirstName
{
get => _firstName;
set
{
_firstName = value;
_fullName = null;
}
}
private string? _lastName;
public string? LastName
{
get => _lastName;
set
{
_lastName = value;
_fullName = null;
}
}
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Ta ostateczna FullName
wersja ocenia właściwość tylko wtedy, gdy jest to konieczne. Poprzednio obliczona wersja jest używana, jeśli jest prawidłowa. W przeciwnym razie obliczenie aktualizuje buforowane wartości. Deweloperzy korzystający z tej klasy nie muszą znać szczegółów implementacji. Żadne z tych zmian wewnętrznych nie ma wpływu na użycie obiektu Person.
Począwszy od języka C# 13, można tworzyć partial
właściwości w partial
klasach. Deklaracja implementowania właściwości partial
nie może być automatycznie zaimplementowaną właściwością. Właściwość zaimplementowana automatycznie używa tej samej składni co deklarowanie deklaracji właściwości częściowej.
Właściwości
Właściwości są formą pól inteligentnych w klasie lub obiekcie. Z zewnątrz obiektu są one wyświetlane jak pola w obiekcie. Można jednak zaimplementować właściwości przy użyciu pełnej palety funkcji języka C#. Możesz zapewnić walidację, różne ułatwienia dostępu, leniwą ocenę lub wszelkie wymagania wymagane przez scenariusze.
- Proste właściwości, które nie wymagają niestandardowego kodu dostępu, można zaimplementować jako definicje treści wyrażenia lub automatycznie zaimplementowane właściwości.
- Właściwości umożliwiają klasie uwidacznianie publicznego sposobu uzyskiwania i ustawiania wartości podczas ukrywania implementacji lub kodu weryfikacyjnego.
- Metodę dostępu do właściwości get służy do zwracania wartości właściwości, a element dostępu właściwości zestawu służy do przypisywania nowej wartości. Akcesor właściwości init służy do przypisywania nowej wartości tylko podczas budowy obiektu. Te metody dostępu mogą mieć różne poziomy dostępu. Aby uzyskać więcej informacji, zobacz Ograniczanie ułatwień dostępu dostępu.
- Słowo kluczowe value służy do definiowania wartości
set
przypisywanej przez metodę lubinit
metody dostępu. - Właściwości mogą być do odczytu i zapisu (mają zarówno
get
metodę dostępu, jak iset
metodę dostępu), tylko do odczytu (mająget
metodę dostępu, ale bezset
metody dostępu) lub tylko do zapisu (mająset
akcesorium, ale bezget
akcesoriów). Właściwości tylko do zapisu są rzadkie.
Specyfikacja języka C#
Aby uzyskać więcej informacji, zobacz Właściwości w specyfikacji języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.
Zobacz też
- Indexers (Indeksatory)
- init , słowo kluczowe
- get słowo kluczowe
- ustaw słowo kluczowe