Dela via


Egenskaper (C#-programmeringsguide)

En egenskap är en medlem som tillhandahåller en flexibel mekanism för att läsa, skriva eller beräkna värdet för ett datafält. Egenskaper visas som medlemmar i offentliga data, men de implementeras som särskilda metoder som kallas accessorer. Den här funktionen gör det möjligt för anropare att enkelt komma åt data och bidrar fortfarande till att främja datasäkerhet och flexibilitet. Syntaxen för egenskaper är ett naturligt tillägg till fält. Ett fält definierar en lagringsplats:

public class Person
{
    public string? FirstName;

    // Omitted for brevity.
}

Auto-implementerade egenskaper

En egenskapsdefinition innehåller deklarationer för en get och-accessor set som hämtar och tilldelar värdet för den egenskapen:

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

    // Omitted for brevity.
}

Föregående exempel visar en automatiskt implementerad egenskap. Kompilatorn genererar ett dolt bakgrundsfält för egenskapen. Kompilatorn implementerar också brödtexten för get och set -accessorerna. Alla attribut tillämpas på den automatiskt implementerade egenskapen. Du kan använda attributet för det kompilatorgenererade bakgrundsfältet genom att ange taggen field: för attributet.

Du kan initiera en egenskap till ett annat värde än standardvärdet genom att ange ett värde efter den avslutande klammerparentesen för egenskapen. Du kanske föredrar att det ursprungliga värdet för egenskapen är den tomma strängen i stället nullför FirstName . Du anger det enligt följande kod:

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

    // Omitted for brevity.
}

Åtkomstkontroll

Föregående exempel visade läs-/skrivegenskaper. Du kan också skapa skrivskyddade egenskaper eller ge olika hjälpmedel till uppsättningen och få åtkomst. Anta att klassen Person endast ska aktivera ändring av värdet för FirstName egenskapen från andra metoder i den klassen. Du kan ge den inställda åtkomstorn private hjälpmedel i stället publicför :

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

    // Omitted for brevity.
}

Egenskapen FirstName kan läsas från valfri kod, men den kan endast tilldelas från kod i Person klassen.

Du kan lägga till alla restriktiva åtkomstmodifierare i antingen uppsättningen eller hämta accessorer. En åtkomstmodifierare för en enskild accessor måste vara mer restriktiv än åtkomsten till egenskapen. Föregående kod är laglig eftersom egenskapen FirstName är public, men den angivna accessorn är private. Det gick inte att deklarera en private egenskap med en public accessor. Egenskapsdeklarationer kan också deklareras protected, internal, protected internaleller till och med private.

Det finns två särskilda åtkomstmodifierare för set accessorer:

  • En set accessor kan ha init som åtkomstmodifierare. Den set accessorn kan bara anropas från en objektinitierare eller typens konstruktorer. Det är mer restriktivt än private för set accessorn.
  • En automatiskt implementerad egenskap kan deklarera en get accessor utan set åtkomst. I så fall tillåter set kompilatorn att åtkomstorn endast anropas från typens konstruktorer. Det är mer restriktivt än init accessorns set åtkomst.

Person Ändra klassen så här:

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

    public string FirstName { get; }

    // Omitted for brevity.
}

Föregående exempel kräver att anropare använder konstruktorn som innehåller parametern FirstName . Anropare kan inte använda objektinitierare för att tilldela egenskapen ett värde. Om du vill stödja initialiserare kan du göra set accessorn till en init accessor, som du ser i följande kod:

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

    public string? FirstName { get; init; }

    // Omitted for brevity.
}

Dessa modifierare används ofta med required modifieraren för att framtvinga korrekt initiering.

Nödvändiga egenskaper

I föregående exempel kan en anropare skapa en Person med hjälp av standardkonstruktorn, utan att FirstName ange egenskapen. Egenskapen ändrade typen till en nullbar sträng. Från och med C# 11 kan du kräva att anropare anger en egenskap:

public class Person
{
    public Person() { }

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

    public required string FirstName { get; init; }

    // Omitted for brevity.
}

Föregående kod gör två ändringar i Person klassen. Först innehåller egenskapsdeklarationen FirstName required modifieraren. Det innebär att all kod som skapar en ny Person måste ange den här egenskapen med hjälp av en objektinitierare. För det andra har konstruktorn som tar en firstName parameter attributet System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute . Det här attributet informerar kompilatorn om att konstruktorn anger alla required medlemmar. Anropare som använder den här konstruktorn behöver inte ange required egenskaper med en objektinitierare.

Viktigt!

Blanda inte ihop required med icke-nullable. Det är giltigt att ange en required egenskap till null eller default. Om typen inte är nullbar, till exempel string i de här exemplen, utfärdar kompilatorn en varning.

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

Uttryckstextdefinitioner

Egenskapsåtkomster består ofta av enrads-instruktioner. Åtkomsterna tilldelar eller returnerar resultatet av ett uttryck. Du kan implementera dessa egenskaper som uttrycksbaserade medlemmar. Uttryckstextdefinitioner består av => token följt av uttrycket som ska tilldelas till eller hämtas från egenskapen.

Skrivskyddade egenskaper kan implementera get accessorn som en uttrycksbaserad medlem. I följande exempel implementeras den skrivskyddade Name egenskapen som en uttrycksbaserad medlem:

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

Egenskapen Name är en beräknad egenskap. Det finns inget bakgrundsfält för Name. Egenskapen beräknar den varje gång.

Egenskaper med bakgrundsfält

Du kan blanda begreppet beräknad egenskap med ett privat fält och skapa en cachelagrad utvärderad egenskap. Uppdatera till exempel FullName egenskapen så att strängformateringen sker vid den första åtkomsten:

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

Den här implementeringen fungerar eftersom FirstName egenskaperna och LastName är skrivskyddade. Folk kan ändra sitt namn. FirstName Om du uppdaterar egenskaperna och LastName för att tillåta set åtkomstorer måste du ogiltigförklara alla cachelagrade värden för fullName. Du ändrar åtkomsterna FirstName för set egenskapen och LastName så att fältet fullName beräknas igen:

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

Den här slutliga versionen utvärderar endast egenskapen när det FullName behövs. Den tidigare beräknade versionen används om den är giltig. Annars uppdaterar beräkningen det cachelagrade värdet. Utvecklare som använder den här klassen behöver inte känna till informationen om implementeringen. Ingen av dessa interna ändringar påverkar användningen av personobjektet.

Från och med C# 13 kan du skapa partial egenskaper i partial klasser. Implementeringsdeklarationen för en partial egenskap kan inte vara en automatiskt implementerad egenskap. En automatiskt implementerad egenskap använder samma syntax som en deklarerande partiell egenskapsdeklaration.

Egenskaper

Egenskaper är en form av smarta fält i en klass eller ett objekt. Utanför objektet visas de som fält i objektet. Egenskaper kan dock implementeras med hjälp av den fullständiga paletten med C#-funktioner. Du kan tillhandahålla validering, olika hjälpmedel, lat utvärdering eller eventuella krav som dina scenarier behöver.

  • Enkla egenskaper som inte kräver någon anpassad åtkomstkod kan implementeras antingen som uttryckstextdefinitioner eller som automatiskt implementerade egenskaper.
  • Med egenskaper kan en klass exponera ett offentligt sätt att hämta och ange värden, samtidigt som implementerings- eller verifieringskoden döljs.
  • En get-egenskapsåtkomstor används för att returnera egenskapsvärdet och en uppsättning egenskapsåtkomst används för att tilldela ett nytt värde. En init-egenskapsåtkomstor används endast för att tilldela ett nytt värde under objektkonstruktionen. Dessa accessorer kan ha olika åtkomstnivåer. Mer information finns i Begränsa hjälpmedel för accessorer.
  • Nyckelordet värde används för att definiera det värde set som eller init -accessorn tilldelar.
  • Egenskaper kan vara skrivskyddade (de har både en get och en set accessor), skrivskyddade (de har en get accessor men ingen set accessor) eller skrivskyddade (de har en set accessor, men ingen get accessor). Skrivskyddade egenskaper är sällsynta.

Språkspecifikation för C#

Mer information finns i Egenskaper i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.

Se även