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.
}
Automatiskt 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 null
för FirstName
. Du anger det enligt följande kod:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
Fältstödda egenskaper
I C# 13 kan du lägga till validering eller annan logik i accessorn för en egenskap med hjälp av funktionen för förhandsversion av field
nyckelord. Nyckelordet field
kommer åt kompilatorns syntetiserade bakgrundsfält för en egenskap. Det gör att du kan skriva en egenskapsåtkomstor utan att uttryckligen deklarera ett separat bakgrundsfält.
public class Person
{
public string? FirstName
{
get;
set => field = value.Trim();
}
// Omitted for brevity.
}
Viktigt!
Nyckelordet field
är en förhandsgranskningsfunktion i C# 13. Du måste använda .NET 9 och ange <LangVersion>
elementet till preview
i projektfilen för att kunna använda det kontextuella nyckelordet field
.
Du bör vara försiktig med att använda nyckelordsfunktionen field
i en klass som har ett fält med namnet field
. Det nya field
nyckelordet skuggar ett fält med namnet field
i omfånget för en egenskapsåtkomst. Du kan antingen ändra namnet på variabeln field
eller använda @
token för att referera till identifieraren field
som @field
. Du kan läsa mer genom att läsa funktionsspecifikationen för nyckelordetfield
.
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.
Å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 klassen. Du kan ge den inställda åtkomstorn private
hjälpmedel i stället internal
för eller public
:
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 internal
eller till och med private
.
Det finns två särskilda åtkomstmodifierare för set
accessorer:
- En
set
accessor kan hainit
som åtkomstmodifierare. Denset
accessorn kan bara anropas från en objektinitierare eller typens konstruktorer. Det är mer restriktivt änprivate
förset
accessorn. - En automatiskt implementerad egenskap kan deklarera en
get
accessor utan åtkomstset
. I så fall tillåterset
kompilatorn att åtkomstorn endast anropas från typens konstruktorer. Det är mer restriktivt äninit
accessornsset
å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.
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 ellerinit
-accessorn tilldelar. - Egenskaper kan vara skrivskyddade (de har både en
get
och enset
accessor), skrivskyddade (de har enget
accessor men ingenset
accessor) eller skrivskyddade (de har enset
accessor, men ingenget
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.