Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Właściwości łączą aspekty pól i metod. Dla użytkownika obiektu właściwość wydaje się być polem; uzyskiwanie dostępu do właściwości wymaga tej samej składni. Dla twórcy klasy, właściwość to jeden lub dwa bloki kodu, reprezentujące akcesor get
i/lub akcesor set
lub init
. Blok kodu dla akcesora get
jest wykonywany, gdy właściwość jest odczytywana; blok kodu dla akcesora set
lub init
jest wykonywany, gdy właściwości przypisuje się wartość. Właściwość bez akcesora set
jest uważana za właściwość tylko do odczytu. Właściwość bez get
metody dostępu jest uważana za właściwość tylko zapisu. Właściwość, która ma oba metody dostępu, to odczyt i zapis. Można użyć init
akcesora zamiast set
akcesora, aby umożliwić ustawienie właściwości podczas inicjowania obiektu, ale w przeciwnym razie uczynić ją tylko do odczytu.
W przeciwieństwie do pól właściwości nie są klasyfikowane jako zmienne. W związku z tym nie można przekazać właściwości jako parametru ref
lub out
.
Właściwości mają wiele zastosowań:
- Mogą weryfikować dane przed zezwoleniem na zmianę.
- Mogą one w sposób przejrzysty uwidaczniać dane w klasie, w której te dane są pobierane z innego źródła, np. z bazy danych.
- Mogą podjąć akcję, gdy dane zostaną zmienione, takie jak podniesienie zdarzenia lub zmiana wartości innych pól.
Właściwości są deklarowane w bloku klasy poprzez określenie poziomu dostępu pola, typu właściwości, nazwy właściwości oraz bloku kodu, który deklaruje akcesor get
i/lub akcesor set
. Na przykład:
public class Date
{
private int _month = 7; // Backing store
public int Month
{
get => _month;
set
{
if ((value > 0) && (value < 13))
{
_month = value;
}
}
}
}
W tym przykładzie Month
jest zadeklarowany jako właściwość, dzięki czemu akcesor set
może upewnić się, że wartość Month
jest ustawiona między 1 a 12. Właściwość Month
używa pola prywatnego do śledzenia rzeczywistej wartości. Rzeczywista lokalizacja danych właściwości jest często określana jako "magazyn zapasowy" właściwości. Właściwości często używają pól prywatnych jako magazynu zapasowego. Pole jest oznaczone jako prywatne, aby upewnić się, że można je zmienić tylko przez wywołanie właściwości . Aby uzyskać więcej informacji na temat ograniczeń dostępu publicznego i prywatnego, zobacz Modyfikatory dostępu. Automatycznie zaimplementowane właściwości zapewniają uproszczoną składnię dla prostych deklaracji właściwości. Aby uzyskać więcej informacji, zobacz Automatycznie zaimplementowane właściwości.
Począwszy od C# 13, można użyć właściwości wspieranych przez pola, aby dodać walidację do set
akcesora automatycznie zaimplementowanej właściwości, jak przedstawiono w poniższym przykładzie:
public class DateExample
{
public int Month
{
get;
set
{
if ((value > 0) && (value < 13))
{
field = value;
}
}
}
}
Ważne
Słowo kluczowe field
jest funkcją zapoznawczą w języku C# 13. Musisz używać platformy .NET 9 i ustawić element <LangVersion>
na preview
w pliku projektu, aby użyć kontekstowego słowa kluczowego field
.
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 przysłania pole o nazwie field
w zakresie akcesora właściwości. Możesz zmienić nazwę zmiennej field
lub użyć tokenu @
, aby odwołać się do identyfikatora field
jako @field
. Możesz dowiedzieć się więcej, czytając specyfikację funkcji dla słowa kluczowego field
.
Akcesor get
Ciało get
akcesora przypomina ciało metody. Musi zwrócić wartość typu właściwości. Kompilator C# i kompilator Just-in-time (JIT) wykrywają typowe wzorce implementowania akcesora get
i optymalizują te wzorce. Na przykład akcesor zwracający get
pole bez wykonywania żadnych obliczeń jest prawdopodobnie zoptymalizowany do odczytu pamięci tego pola. Automatycznie zaimplementowane właściwości są zgodne z tym wzorcem i korzystają z tych optymalizacji. Nie można jednak wbudować wirtualnej metody dostępu get
, ponieważ w czasie kompilacji kompilator nie wie, która metoda może być faktycznie wywoływana w czasie wykonywania. W poniższym przykładzie przedstawiono akcesor get
, który zwraca wartość prywatnego pola _name
:
class Employee
{
private string _name; // the name field
public string Name => _name; // the Name property
}
Gdy odwołujesz się do właściwości, z wyjątkiem sytuacji, gdy jest ona celem przypisania, metoda dostępu get
jest wywoływana w celu odczytania wartości tej właściwości. Na przykład:
var employee = new Employee();
//...
System.Console.Write(employee.Name); // the get accessor is invoked here
Akcesor get
musi być elementem z wyrażeniem lambda, lub kończyć się instrukcją return lub throw, i przepływ sterowania nie może wyjść poza ciało akcesora.
Ostrzeżenie
Zazwyczaj zmienianie stanu obiektu za pomocą akcesora jest uważane za zły styl programowania. Jednym wyjątkiem od tej reguły jest leniwa oceniana właściwość, w której wartość właściwości jest obliczana tylko wtedy, gdy zostanie po raz pierwszy wywołana.
Metody dostępowej get
można używać do zwracania wartości pola lub jej obliczenia i zwrócenia. Na przykład:
class Manager
{
private string _name;
public string Name => _name != null ? _name : "NA";
}
W poprzednim przykładzie, jeśli nie przypiszesz wartości do Name
właściwości, zwraca wartość NA
.
Akcesorium zestawu
set
metoda dostępu przypomina metodę, której typ zwracany to void. Używa niejawnego parametru o nazwie value
, którego typem jest typ właściwości. Kompilator i kompilator JIT rozpoznają również typowe wzorce dla elementu set
lub init
akcesora. Te typowe wzorce są zoptymalizowane, bezpośrednio zapisując pamięć dla pola zapasowego. W poniższym przykładzie do właściwości set
dodawany jest Name
akcesor:
class Student
{
private string _name; // the name field
public string Name // the Name property
{
get => _name;
set => _name = value;
}
}
Gdy przypisujesz wartość do właściwości, akcesor set
jest wywoływany przy użyciu argumentu, który dostarcza nową wartość. Na przykład:
var student = new Student();
student.Name = "Joe"; // the set accessor is invoked here
System.Console.Write(student.Name); // the get accessor is invoked here
Jest to błąd użycia niejawnej nazwy parametru value
dla deklaracji zmiennej lokalnej w akcesorze set
.
Metoda dostępu inicjująca
Kod utworzenia init
jest taki sam jak kod utworzenia set
z tą różnicą, że używasz słowa kluczowego init
zamiast set
. Różnica polega na tym, że init
akcesor może być używany tylko w konstruktorze lub za pomocą inicjalizatora obiektu.
Uwagi
Właściwości można oznaczyć jako public
, , private
, protected
internal
, , protected internal
lub private protected
. Te modyfikatory dostępu definiują sposób, w jaki użytkownicy klasy mogą uzyskiwać dostęp do właściwości. Akcesory get
i set
dla tej samej właściwości mogą mieć różne modyfikatory dostępu. Na przykład get
może to być public
zezwolenie na dostęp tylko do odczytu spoza typu, a set
może to być private
lub protected
. Aby uzyskać więcej informacji, zobacz Modyfikatory dostępu.
Właściwość można zadeklarować jako właściwość statyczną przy użyciu słowa kluczowego static
. Właściwości statyczne są dostępne dla wywołujących w każdym momencie, nawet jeśli żadne wystąpienie klasy nie istnieje. Aby uzyskać więcej informacji, zobacz Klasy statyczne i składowe klas statycznych.
Właściwość można oznaczyć jako właściwość wirtualną za pomocą słowa kluczowego wirtualnego. Właściwości wirtualne umożliwiają klasom pochodnym zastąpienie zachowania właściwości za pomocą słowa kluczowego override. Aby uzyskać więcej informacji na temat tych opcji, zobacz Dziedziczenie.
Właściwość przesłaniająca właściwość wirtualną może być również zapieczętowana, określając, że dla klas pochodnych nie jest już wirtualna. Na koniec właściwość można zadeklarować jako abstrakcyjną. Właściwości abstrakcyjne nie definiują implementacji w klasie, a klasy pochodne muszą napisać własną implementację. Aby uzyskać więcej informacji na temat tych opcji, zobacz Klasy abstrakcyjne i zamknięte oraz członkowie klasy.
Uwaga
Jest błędem użycie modyfikatora wirtualnego, abstrakcyjnego lub zastępującego w metodzie dostępu do właściwości statycznej.
Przykłady
Ten przykład demonstruje właściwości obiektowe, statyczne i tylko do odczytu. Akceptuje imię pracownika z klawiatury, zwiększa NumberOfEmployees
o 1, a następnie wyświetla imię i numer pracownika.
public class Employee
{
public static int NumberOfEmployees;
private static int _counter;
private string _name;
// A read-write instance property:
public string Name
{
get => _name;
set => _name = value;
}
// A read-only static property:
public static int Counter => _counter;
// A Constructor:
public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}
Przykład ukrytej właściwości
W tym przykładzie pokazano, jak uzyskać dostęp do właściwości w klasie bazowej ukrytej przez inną właściwość o tej samej nazwie w klasie pochodnej:
public class Employee
{
private string _name;
public string Name
{
get => _name;
set => _name = value;
}
}
public class Manager : Employee
{
private string _name;
// Notice the use of the new modifier:
public new string Name
{
get => _name;
set => _name = value + ", Manager";
}
}
class TestHiding
{
public static void Test()
{
Manager m1 = new Manager();
// Derived class property.
m1.Name = "John";
// Base class property.
((Employee)m1).Name = "Mary";
System.Console.WriteLine($"Name in the derived class is: {m1.Name}");
System.Console.WriteLine($"Name in the base class is: {((Employee)m1).Name}");
}
}
/* Output:
Name in the derived class is: John, Manager
Name in the base class is: Mary
*/
Poniżej przedstawiono ważne kwestie w poprzednim przykładzie:
- Właściwość
Name
w klasie pochodnej ukrywa właściwośćName
w klasie bazowej. W takim przypadkunew
modyfikator jest używany w deklaracji właściwości w klasie pochodnej:public new string Name
-
(Employee)
Rzutowanie służy do uzyskiwania dostępu do ukrytej właściwości w klasie bazowej:((Employee)m1).Name = "Mary";
Aby uzyskać więcej informacji na temat ukrywania członków, zobacz nowy modyfikator.
Przykład przesłonięcia właściwości
W tym przykładzie dwie klasy Cube
i Square
, implementują klasę abstrakcyjną, Shape
i przesłaniają jej właściwość abstrakcyjną Area
. Zwróć uwagę na użycie modyfikatora przesłonięcia we właściwościach. Program akceptuje bok jako dane wejściowe i oblicza pola dla kwadratu i sześcianu. Akceptuje również obszar jako dane wejściowe i oblicza odpowiednią stronę kwadratu i modułu.
abstract class Shape
{
public abstract double Area
{
get;
set;
}
}
class Square : Shape
{
public double side;
//constructor
public Square(double s) => side = s;
public override double Area
{
get => side * side;
set => side = System.Math.Sqrt(value);
}
}
class Cube : Shape
{
public double side;
//constructor
public Cube(double s) => side = s;
public override double Area
{
get => 6 * side * side;
set => side = System.Math.Sqrt(value / 6);
}
}
class TestShapes
{
static void Main()
{
// Input the side:
System.Console.Write("Enter the side: ");
double side = double.Parse(System.Console.ReadLine());
// Compute the areas:
Square s = new Square(side);
Cube c = new Cube(side);
// Display the results:
System.Console.WriteLine($"Area of the square = {s.Area:F2}");
System.Console.WriteLine($"Area of the cube = {c.Area:F2}");
System.Console.WriteLine();
// Input the area:
System.Console.Write("Enter the area: ");
double area = double.Parse(System.Console.ReadLine());
// Compute the sides:
s.Area = area;
c.Area = area;
// Display the results:
System.Console.WriteLine($"Side of the square = {s.side:F2}");
System.Console.WriteLine($"Side of the cube = {c.side:F2}");
}
}
/* Example Output:
Enter the side: 4
Area of the square = 16.00
Area of the cube = 96.00
Enter the area: 24
Side of the square = 4.90
Side of the cube = 2.00
*/