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ým rozšířením 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 přístupové metody get a set, které získávají a přiřazují 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 dávat přednost, aby počáteční hodnota vlastnosti FirstName byla prázdným řetězcem spíše než null. Můžete to specifikovat, 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 C# 13 můžete do přistupovače vlastnosti přidat ověření nebo jinou logiku pomocí náhledové funkce klíčového slova field. Klíčové field slovo přistupuje k kompilátorem syntetizovanému podpůrnému poli vlastnosti. 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 náhledová funkce v jazyce C# 13. Pokud chcete použít <LangVersion> kontextové klíčové slovo, musíte používat .NET 9 a nastavit prvek preview ve vašem souboru projektu na field.

Měli byste být opatrní při používání funkce klíčového slova field v 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 vytvořit Person s využitím výchozího konstruktoru, aniž by byla nastavena vlastnost FirstName. Vlastnost změnila typ na nulovatelný řetězec. 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šechnyrequired členy. Volající používající tento konstruktor nemusí nastavovat required vlastnosti s použitím inicializátoru objektu.

Důležité

Nezaměňujte required s nenulovou hodnotou. Je platné nastavit vlastnost required na hodnotu null 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 výrazového těla

Přístupy k vlastnostem často sestávají z jednořádkových příkazů. Přístupové funkce přiřazují nebo vracejí výsledek výrazu. Tyto vlastnosti můžete implementovat jako členy s výrazovým tělem. 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 pro čtení Name jako člen se syntaxí výrazu.

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 to 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. Můžete nastavit přístupnost pro nastavovací metodu private namísto internal nebo 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ě.

Můžete přidat libovolný modifikátor omezující přístup k set nebo get přístupovým metodám. 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 vlastnost private s akcesorem 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řístupový prvek lze volat pouze z inicializátoru objektu nebo z konstruktorů typu. Je to více omezující než private u přístupového prvku set.
  • Automaticky implementovaná vlastnost může deklarovat get přístupovou metodu bez přístupové metody 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 udělat ze set přístupový objekt 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 k formátování řetězců došlo při prvním 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 a LastName jsou jen pro čtení. Lidé můžou změnit jméno. Aktualizace vlastností FirstName a LastName tak, aby umožňovaly set přístupové metody, vyžaduje, abyste zneplatnili jakoukoli hodnotu uloženou v mezipaměti pro fullName. Upravíte přístupové objekty vlastnosti set a FirstName tak, aby se pole LastName 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ůznou přístupnost, lí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.
  • Pro vrácení hodnoty vlastnosti se používá přístupová metoda get a pro přiřazení nové hodnoty se používá přístupová metoda set. Přístupový prvek vlastnosti init se používá k přiřazení nové hodnoty pouze během vytváření objektu. 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 'hodnota' slouží k definování hodnoty, kterou přiřazuje přístupový prvek set nebo init.
  • Vlastnosti můžou být pro čtení a zápis (mají přístupový get i set objekt), jen pro čtení (mají přístupový get objekt, ale žádný set objekt) nebo jen pro zápis (mají set přístupový objekt, ale žádný get objekt). 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é