Eigenschappen (C#-programmeerhandleiding)
Een eigenschap is een lid dat een flexibel mechanisme biedt voor het lezen, schrijven of berekenen van de waarde van een gegevensveld. Eigenschappen worden weergegeven als openbare gegevensleden, maar ze worden geïmplementeerd als speciale methoden genaamd accessors. Met deze functie kunnen bellers eenvoudig toegang krijgen tot gegevens en kunnen ze nog steeds de veiligheid en flexibiliteit van gegevens bevorderen. De syntaxis voor eigenschappen is een natuurlijke uitbreiding op velden. Een veld definieert een opslaglocatie:
public class Person
{
public string? FirstName;
// Omitted for brevity.
}
Automatisch geïmplementeerde eigenschappen
Een eigenschapsdefinitie bevat declaraties voor een get
en set
accessor die de waarde van die eigenschap ophaalt en toewijst:
public class Person
{
public string? FirstName { get; set; }
// Omitted for brevity.
}
In het voorgaande voorbeeld ziet u een automatisch geïmplementeerde eigenschap. De compiler genereert een verborgen achterliggend veld voor de eigenschap. De compiler implementeert ook de hoofdtekst van de get
en set
accessors. Alle kenmerken worden toegepast op de automatisch geïmplementeerde eigenschap. U kunt het kenmerk toepassen op het door de compiler gegenereerde backingveld door de field:
tag op te geven op het kenmerk.
U kunt een eigenschap initialiseren met een andere waarde dan de standaard door een waarde in te stellen na de sluitende accolade van de eigenschap. Mogelijk geeft u de voorkeur aan de oorspronkelijke waarde voor de FirstName
eigenschap om de lege tekenreeks te zijn in plaats van null
. U geeft dit op zoals wordt weergegeven in de volgende code:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
Eigenschappen ondersteund door een veld
In C# 13 kunt u validatie of andere logica toevoegen aan de accessor van een eigenschap met behulp van de previewfunctie voor trefwoorden. Het field
trefwoord verleent toegang tot het gesynthetiseerde backingveld van de compiler voor een eigenschap. Hiermee kunt u een eigenschapstoegangsor schrijven zonder expliciet een afzonderlijk backingveld te declareren.
public class Person
{
public string? FirstName
{
get;
set => field = value.Trim();
}
// Omitted for brevity.
}
Belangrijk
Het field
trefwoord is een preview-functie in C# 13. U moet .NET 9 gebruiken en het <LangVersion>
element preview
instellen op in uw projectbestand om het field
contextuele trefwoord te kunnen gebruiken.
Wees voorzichtig met het gebruik van de trefwoordfunctie in een klasse met een veld met de field
naam field
. Het nieuwe field
trefwoord schaduwt een veld met de naam field
in het bereik van een eigenschapstoegangsor. U kunt de naam van de field
variabele wijzigen of het @
token gebruiken om naar de field
id te verwijzen.@field
Meer informatie vindt u door de functiespecificatie voor het field
trefwoord te lezen.
Vereiste eigenschappen
In het voorgaande voorbeeld kan een aanroeper een Person
maken met behulp van de standaardconstructor, zonder de FirstName
eigenschap in te stellen. Het eigenschapstype is gewijzigd in een tekenreeks die null kan worden gebruikt. Vanaf C# 11 kunt u vereisen dat bellers een eigenschap instellen:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
// Omitted for brevity.
}
De voorgaande code brengt twee wijzigingen aan in de Person
klasse. Eerst bevat de FirstName
eigenschapsdeclaratie de required
wijzigingsfunctie. Dit betekent dat elke code die een nieuwe Person
maakt, deze eigenschap moet instellen met behulp van een object-initialisatiefunctie. Ten tweede heeft de constructor die een firstName
parameter gebruikt het System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute kenmerk. Dit kenmerk informeert de compiler dat deze constructor allerequired
leden instelt. Bellers die deze constructor gebruiken, hoeven geen eigenschappen in te stellen met een objectinitializer.
Belangrijk
Verwar required
niet met niet-nullable. Het is geldig om een required
eigenschap in te stellen op null
of default
. Als het type niet null-compatibel is, zoals string
in deze voorbeelden, geeft de compiler een waarschuwing.
var aPerson = new Person("John");
aPerson = new Person { FirstName = "John"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();
Definities van expressielichaam
Eigenschapstoegangsors bestaan vaak uit instructies met één regel. De accessors wijzen ofwel het resultaat van een expressie toe, of ze retourneren het. U kunt deze eigenschappen implementeren als expressielichaamleden. Hoofdtekstdefinities van expressies bestaan uit het =>
token, gevolgd door de expressie die moet worden toegewezen aan of opgehaald uit de eigenschap.
Eigenschappen met het kenmerk Alleen-lezen kunnen de get
toegangsfunctie implementeren als een expressie-lid. In het volgende voorbeeld wordt de eigenschap Alleen-lezen Name
geïmplementeerd als een expressielid:
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.
}
De Name
eigenschap is een berekende eigenschap. Er is geen ondersteunend veld voor Name
. De eigenschap berekent deze elke keer.
Toegangsbeheer
In de voorgaande voorbeelden zijn lees-/schrijfeigenschappen weergegeven. U kunt ook alleen-lezeneigenschappen maken of andere toegankelijkheid geven aan de set en accessors ophalen. Stel dat uw Person
klasse alleen het wijzigen van de waarde van de FirstName
eigenschap van andere methoden in de klasse moet inschakelen. U kunt de toegankelijkheid van de settoegangsfunctie private
geven in plaats van internal
of public
.
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
De FirstName
eigenschap kan worden gelezen uit elke code, maar kan alleen worden toegewezen vanuit code in de Person
klasse.
U kunt elke beperkende toegangsmodificator toevoegen op de set- of get-toegangsmethode. Een toegangsmodifier voor een afzonderlijke accessor moet meer beperkend zijn dan de toegang van de eigenschap. De voorgaande code is legaal omdat de FirstName
eigenschap is public
, maar de set accessor is private
. U kunt een private
eigenschap met een public
accessor niet declareren. Eigenschapsdeclaraties kunnen ook worden gedeclareerd protected
, internal
, protected internal
of zelfs private
.
Er zijn twee speciale toegangsaanpassingen voor set
accessors:
- Een
set
toegangsmethode kaninit
als zijn toegangsmodifier hebben. Dezeset
accessor kan alleen worden aangeroepen vanuit een object-initialisatiefunctie of de constructors van het type. Het is meer beperkend danprivate
deset
accessor. - Een automatisch geïmplementeerde eigenschap kan een
get
accessor declareren zonder eenset
accessor. In dat geval staat de compiler toe dat deset
accessor alleen kan worden aangeroepen vanuit de constructors van het type. Het is beperkter dan deinit
accessor op deset
accessor.
Wijzig de Person
klasse als volgt:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
In het voorgaande voorbeeld moeten bellers de constructor gebruiken die de FirstName
parameter bevat. Bellers kunnen geen object-initializers gebruiken om een waarde toe te wijzen aan de eigenschap. Om initialisators te ondersteunen, kunt u de set
-accesseerder een init
-accesseermethode maken, zoals wordt weergegeven in de volgende code:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Deze modifiers worden vaak gebruikt met de required
modifier om de juiste initialisatie af te dwingen.
Eigenschappen met onderliggende velden
U kunt het concept van een berekende eigenschap combineren met een privéveld en een geëvalueerde eigenschap in de cache maken. Werk bijvoorbeeld de FullName
eigenschap bij zodat de tekenreeksopmaak op de eerste toegang plaatsvindt:
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;
}
}
}
Deze implementatie werkt omdat de eigenschappen FirstName
en LastName
alleen-lezen zijn. Mensen kunnen hun naam wijzigen. Als u de eigenschappen FirstName
en LastName
bijwerkt om set
-accessors toe te staan, moet u elke cachewaarde voor fullName
ongeldig maken. U wijzigt de set
toegangsrechten van de FirstName
en LastName
eigenschap zodat het fullName
veld opnieuw wordt berekend:
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;
}
}
}
Deze definitieve versie evalueert de FullName
eigenschap alleen wanneer dat nodig is. De eerder berekende versie wordt gebruikt indien geldig. Anders werkt de berekening de waarde in de cache bij. Ontwikkelaars die deze klasse gebruiken, hoeven de details van de implementatie niet te weten. Geen van deze interne wijzigingen heeft invloed op het gebruik van het object Person.
Vanaf C# 13 kunt u partial
eigenschappen in partial
klassen maken. De implementatiedeclaratie voor een partial
eigenschap kan geen automatisch geïmplementeerde eigenschap zijn. Een automatisch geïmplementeerde eigenschap maakt gebruik van dezelfde syntaxis als een declaratie van gedeeltelijke eigenschappen.
Eigenschappen
Eigenschappen zijn een vorm van slimme velden in een klasse of object. Van buiten het object worden ze weergegeven als velden in het object. Eigenschappen kunnen echter worden geïmplementeerd met behulp van het volledige palet van C#-functionaliteit. U kunt validatie, verschillende toegankelijkheid, luie evaluatie of eventuele vereisten bieden die uw scenario's nodig hebben.
- Eenvoudige eigenschappen waarvoor geen aangepaste toegangscode is vereist, kunnen worden geïmplementeerd als hoofdtekstdefinities van expressies of als automatisch geïmplementeerde eigenschappen.
- Met eigenschappen kan een klasse een openbare manier weergeven om waarden op te halen en in te stellen, terwijl implementatie- of verificatiecode wordt verborgen.
- Get property accessor wordt gebruikt om de eigenschapswaarde te retourneren en een set property accessor wordt gebruikt om een nieuwe waarde toe te wijzen. Een init-eigenschapstoegangsobject wordt gebruikt om alleen een nieuwe waarde toe te wijzen tijdens het bouwen van objecten. Deze accessors kunnen verschillende toegangsniveaus hebben. Voor meer informatie, zie Toegankelijkheid van accessor beperken.
- Het trefwoord waarde wordt gebruikt om de waarde te definiëren die de
set
ofinit
accessor toewijst. - Eigenschappen kunnen lees-schrijf zijn
(ze hebben zowel een als een accessor), alleen-lezen (ze hebben eenaccessor maar geen accessor), of alleen-schrijven (ze hebben eenaccessor, maar geen accessor). Alleen-schrijfbare eigenschappen zijn zeldzaam.
C#-taalspecificatie
Zie Eigenschappen in de C#-taalspecificatie voor meer informatie. De taalspecificatie is de definitieve bron voor de C#-syntaxis en het gebruik.