Sdílet prostřednictvím


Vlastnosti (Průvodce programováním v C#)

Vlastnost je člen, který poskytuje flexibilní mechanismus pro čtení, zápis nebo výpočet hodnoty datového pole. Vlastnosti se zobrazují jako veřejné datové členy, ale implementují se jako speciální metody označované jako přístupové objekty. Tato funkce umožňuje volajícím snadno přistupovat k datům a stále pomáhá zvýšit bezpečnost a flexibilitu dat. Syntaxe vlastností je přirozené rozšíření polí. Pole definuje umístění úložiště:

public class Person
{
    public string? FirstName;

    // Omitted for brevity.
}

Automaticky implementované vlastnosti

Definice vlastnosti obsahuje deklarace pro get objekt a set přístup, který načte a přiřadí hodnotu této vlastnosti:

public class Person
{
    public string? FirstName { get; set; }

    // Omitted for brevity.
}

Předchozí příklad ukazuje automaticky implementovanou vlastnost. Kompilátor vygeneruje skryté záložní pole pro vlastnost. Kompilátor také implementuje tělo get a set přístupové objekty. Všechny atributy se použijí na automaticky implementovanou vlastnost. Atribut můžete použít u pole backingu vygenerovaného kompilátorem zadáním field: značky atributu.

Vlastnost můžete inicializovat na jinou hodnotu než výchozí nastavením hodnoty za pravou závorkou vlastnosti. Můžete preferovat počáteční hodnotu vlastnosti FirstName , aby byla prázdný řetězec, a ne null. Určíte, jak je znázorněno v následujícím kódu:

public class Person
{
    public string FirstName { get; set; } = string.Empty;

    // Omitted for brevity.
}

Vlastnosti zálohované pole

V jazyce C# 13 můžete do přístupové vlastnosti přidat ověření nebo jinou logiku pomocí funkce Preview klíčového field slova. Klíčové field slovo přistupuje k syntetizovanému záložnímu poli kompilátoru pro vlastnost. Umožňuje psát přístupové objekty vlastností bez explicitního deklarování samostatného záložního pole.

public class Person
{
    public string? FirstName 
    { 
        get;
        set => field = value.Trim(); 
    }

    // Omitted for brevity.
}

Důležité

Klíčové field slovo je funkce preview v jazyce C# 13. Pokud chcete použít field kontextové klíčové slovo, musíte použít .NET 9 a nastavit prvek <LangVersion> do preview souboru projektu.

Měli byste být opatrní pomocí funkce klíčového field slova ve třídě, která má pole s názvem field. Nové field klíčové slovo stínuje pole pojmenované field v oboru přístupového objektu vlastnosti. Můžete změnit název field proměnné nebo pomocí @ tokenu odkazovat na field identifikátor jako @field. Další informace najdete ve specifikaci funkce pro field klíčové slovo.

Požadované vlastnosti

Předchozí příklad umožňuje volajícímu Person vytvořit pomocí výchozího konstruktoru bez nastavení FirstName vlastnosti. Vlastnost změnila typ na řetězec s možnou hodnotou null. Počínaje jazykem C# 11 můžete vyžadovat , aby volající nastavili vlastnost:

public class Person
{
    public Person() { }

    [SetsRequiredMembers]
    public Person(string firstName) => FirstName = firstName;

    public required string FirstName { get; init; }

    // Omitted for brevity.
}

Předchozí kód provede dvě změny Person třídy. Nejprve deklarace FirstName vlastnosti zahrnuje required modifikátor. To znamená, že jakýkoli kód, který vytvoří novouPerson, musí nastavit tuto vlastnost pomocí inicializátoru objektů. Za druhé, konstruktor, který přebírá firstName parametr má System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute atribut. Tento atribut informuje kompilátor, že tento konstruktor nastaví všechny required členy. Volající používající tento konstruktor nejsou potřeba k nastavení required vlastností pomocí inicializátoru objektů.

Důležité

Nezaměňujte required s nenulovou hodnotou. Je platné nastavit required vlastnost na null hodnotu nebo default. Pokud je typ nenulový, například string v těchto příkladech, kompilátor vydá upozornění.

var aPerson = new Person("John");
aPerson = new Person{ FirstName = "John"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();

Definice textu výrazu

Přístupové objekty vlastností se často skládají z jednořádkových příkazů. Přístupové objekty přiřazují nebo vrací výsledek výrazu. Tyto vlastnosti můžete implementovat jako členy s body výrazu. Definice těla výrazu se skládají z tokenu => následovaného výrazem, ke kterému se má přiřadit nebo načíst z vlastnosti.

Vlastnosti jen pro get čtení mohou implementovat přístup jako člen typu výraz bodied. Následující příklad implementuje vlastnost jen Name pro čtení jako výraz-bodied člen:

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

Vlastnost Name je vypočítaná vlastnost. Neexistuje žádné záložní pole pro Name. Tato vlastnost ji pokaždé vypočítá.

Řízení přístupu

Předchozí příklady ukázaly vlastnosti čtení a zápisu. Můžete také vytvořit vlastnosti jen pro čtení nebo nastavit různou přístupnost sady a získat přístupové objekty. Předpokládejme, že vaše Person třída by měla povolit pouze změnu hodnoty FirstName vlastnosti z jiných metod třídy. Přístup k sadě private můžete nastavit tak, aby byl přístup k přístupnosti, nikoli internal public:

public class Person
{
    public string? FirstName { get; private set; }

    // Omitted for brevity.
}

FirstName Vlastnost lze číst z libovolného kódu, ale lze ji přiřadit pouze z kódu ve Person třídě.

K sadě nebo získání přístupových objektů můžete přidat libovolný modifikátor omezujícího přístupu. Modifikátor přístupu u jednotlivého přístupového objektu musí být více omezující než přístup vlastnosti. Předchozí kód je právní, protože vlastnost FirstName je public, ale set příslušenství je private. Nelze deklarovat private vlastnost s příslušenstvím public . Deklarace vlastností lze také deklarovat protected, internal, , protected internalnebo dokonce private.

Existují dva speciální modifikátory přístupu pro set přístupové objekty:

  • Přístupový set objekt může mít init jako modifikátor přístupu. Tento set přístup lze volat pouze z inicializátoru objektů nebo konstruktorů typu. Je to více omezující než private u přístupového objektu set .
  • Automaticky implementovaná vlastnost může deklarovat get příslušenství bez přístupového objektu set . V takovém případě kompilátor umožňuje set , aby se přístupové objekty volaly pouze z konstruktorů typu. Je to více omezující než init přístup na přístupovém objektu set .

Person Upravte třídu následujícím způsobem:

public class Person
{
    public Person(string firstName) => FirstName = firstName;

    public string FirstName { get; }

    // Omitted for brevity.
}

Předchozí příklad vyžaduje, aby volající používali konstruktor, který obsahuje FirstName parametr. Volající nemůžou k přiřazení hodnoty vlastnosti použít inicializátory objektů. Chcete-li podporovat inicializátory, můžete příslušenství nastavit set jako přístup init , jak je znázorněno v následujícím kódu:

public class Person
{
    public Person() { }
    public Person(string firstName) => FirstName = firstName;

    public string? FirstName { get; init; }

    // Omitted for brevity.
}

Tyto modifikátory se často používají s modifikátorem required k vynucení správné inicializace.

Vlastnosti se záložními poli

Koncept počítané vlastnosti můžete kombinovat s privátním polem a vytvořit vyhodnocenou vlastnost uloženou v mezipaměti. Například aktualizujte FullName vlastnost tak, aby se formátování řetězců stalo u prvního přístupu:

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

Tato implementace funguje, protože vlastnosti FirstName jsou LastName jen pro čtení. Lidé můžou změnit jméno. FirstName Aktualizace vlastností takLastName, aby umožňovaly set přístupové objekty, vyžaduje, abyste zneplatňovali jakoukoli hodnotu uloženou v mezipaměti pro fullName. set Upravíte přístupové objekty FirstName a LastName vlastnost tak, aby fullName se pole znovu vypočítalo:

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

Tato konečná verze vyhodnocuje FullName vlastnost pouze v případě potřeby. Dříve počítaná verze se použije, pokud je platná. V opačném případě výpočet aktualizuje hodnotu uloženou v mezipaměti. Vývojáři používající tuto třídu nemusí znát podrobnosti implementace. Žádný z těchto vnitřních změn nemá vliv na použití objektu Person.

Počínaje jazykem C# 13 můžete vytvářet partial vlastnosti ve partial třídách. Implementovaná deklarace vlastnosti partial nemůže být automaticky implementovaná vlastnost. Automaticky implementovaná vlastnost používá stejnou syntaxi jako deklarující částečnou deklaraci vlastnosti.

Vlastnosti

Vlastnosti jsou formou inteligentních polí ve třídě nebo objektu. Zvnějšku objektu se zobrazí jako pole v objektu. Vlastnosti je však možné implementovat pomocí celé palety funkcí jazyka C#. Můžete zadat ověřování, různé přístupnosti, opožděné vyhodnocení nebo jakékoli požadavky, které vaše scénáře potřebují.

  • Jednoduché vlastnosti, které nevyžadují žádný vlastní přístupový kód, lze implementovat buď jako definice těla výrazu, nebo jako automaticky implementované vlastnosti.
  • Vlastnosti umožňují třídě zveřejnit veřejný způsob získání a nastavení hodnot při skrytí implementace nebo ověřovacího kódu.
  • K vrácení hodnoty vlastnosti slouží přístupové objekty get a k přiřazení nové hodnoty se používá objekt pro nastavení vlastnosti. Inicializační objekt vlastnosti se používá k přiřazení nové hodnoty pouze během vytváření objektů. Tyto přístupové objekty můžou mít různé úrovně přístupu. Další informace naleznete v tématu Omezení přístupnosti přístupového objektu.
  • Klíčové slovo hodnoty slouží k definování hodnoty, kterou set přiřazuje.init
  • Vlastnosti můžou být jen pro čtení (mají přístupové set get objekty i přístupové objekty), jen pro čtení (mají přístupové get objekty, ale žádné set přístupové objekty) nebo jen pro zápis (mají set přístupové objekty, ale žádné get přístupové objekty). Vlastnosti jen pro zápis jsou vzácné.

Specifikace jazyka C#

Další informace naleznete v tématu Vlastnosti ve specifikaci jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.

Viz také