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 leden van openbare gegevens, maar ze worden geïmplementeerd als speciale methoden die accessors worden genoemd. 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 back-upveld 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 op een andere waarde dan de standaardwaarde door een waarde in te stellen na de accolade sluiten voor de eigenschap. Mogelijk geeft u de voorkeur aan de oorspronkelijke waarde voor de FirstName
eigenschap als de lege tekenreeks in plaats null
van . U geeft dit op zoals wordt weergegeven in de volgende code:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
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 die klasse moet inschakelen. U kunt de toegankelijkheid van de settoegangsfunctie private
geven in plaats van 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 toegangsaanpassing toevoegen aan de set of get accessors. Een toegangsaanpassing voor een afzonderlijke toegangsfunctie 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
toegangsfunctie kan een toegangsaanpassing hebbeninit
. 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 zonderset
een toegangsfunctie. In dat geval staat de compiler toe dat deset
accessor alleen kan worden aangeroepen vanuit de constructors van het type. Het is meer beperkend dan deinit
accessor op deset
toegangsrechten.
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. Als u initialisatieprogramma's wilt ondersteunen, kunt u de set
accessor een init
toegangsfunctie 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.
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 met deze constructor alle leden worden required
ingesteld. Bellers die deze constructor gebruiken, zijn niet vereist om eigenschappen in te stellen required
met een object-initialisatiefunctie.
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();
Hoofdtekstdefinities voor expressies
Eigenschapstoegangsors bestaan vaak uit instructies met één regel. De accessors wijzen het resultaat van een expressie toe of retourneren. U kunt deze eigenschappen implementeren als leden met expressies. 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 backingveld voor Name
. De eigenschap berekent deze elke keer.
Eigenschappen met back-upvelden
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 FirstName
eigenschappen en LastName
eigenschappen alleen-lezen zijn. Mensen kunnen hun naam wijzigen. Als u de FirstName
eigenschappen LastName
bijwerkt om accessors toe te staan set
, moet u een waarde in de cache ongeldig maken voor fullName
. 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 eigenschappen maken partial
in partial
klassen. 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.
- Een get property accessor wordt gebruikt om de eigenschapswaarde te retourneren en er wordt een set eigenschapstoegangsfunctie 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. Zie Toegankelijkheid van accessor beperken voor meer informatie.
- Het trefwoord waarde wordt gebruikt om de waarde te definiëren die de
set
ofinit
accessor toewijst. - Eigenschappen kunnen lezen/schrijven zijn (ze hebben zowel een
get
als eenset
accessor), alleen-lezen (ze hebben eenget
toegangsbeheerprogramma maar geenset
toegangsrechten), of alleen-schrijven (ze hebben eenset
accessor, maar geenget
toegangsbeheerprogramma). Eigenschappen met alleen-schrijven 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.