Begræns adgang til egenskaber
En klasse kan angive, hvor tilgængelig hvert af dens medlemmer er for at kode uden for klassen. Metoder og variabler, der ikke er beregnet til at blive brugt uden for klassen eller assemblyen, kan skjules for at begrænse risikoen for kodningsfejl eller skadelige udnyttelser.
Nogle metoder og egenskaber er beregnet til at blive kaldt eller tilgået fra kode uden for en klasse, der kaldes klientkode. Andre metoder og egenskaber kan kun bruges i selve klassen. Det er vigtigt at begrænse tilgængeligheden af din kode, så det kun er den tilsigtede klientkode, der kan nå den. Du kan angive, hvor tilgængelige dine typer og deres medlemmer skal være for klientkoden ved hjælp af følgende adgangsændring:
-
public: Typen eller medlemmet er tilgængelig for enhver anden kode i den samme assembly eller en anden assembly, der refererer til den. -
protected: Typen eller medlemmet er kun tilgængelig med kode i samme klasse eller en afledt klasse. -
internal: Typen eller medlemmet er tilgængelig for enhver kode i den samme assembly, men ikke fra en anden assembly. -
protected internal: Typen eller medlemmet er tilgængelig for enhver kode i den samme assembly eller for en hvilken som helst afledt klasse i en anden assembly. -
private: Typen eller medlemmet er kun tilgængelig med kode i samme klasse eller struktur. -
private protected: Typen eller medlemmet er kun tilgængelig med kode i den samme assembly og kun efter kode i den samme klasse eller en afledt klasse.
Klassemedlemmer tildeles som standard private adgang.
Access-modifikatorer på egenskaber og accessors
Indtil nu i modulet fokuserede vi på egenskaber, der omfatter både get og set accessors. Disse egenskaber kaldes læse-/skriveegenskaber. Ud over læse-/skriveegenskaber kan du oprette skrivebeskyttede egenskaber eller give adgangsadgang til set og get accessors.
Som standard har get og set adgangsbrugere det samme tilgængelighedsniveau som den egenskab, de tilhører. Du kan dog begrænse tilgængeligheden af enten get eller set accessor. Adgangsmodifikatorer er nyttige, når du vil begrænse adgangen til selve egenskaben, men stadig tillade adgang til egenskabens værdi via en get accessor.
Antag, at du har en Person klasse, der kun skal aktivere ændring af værdien af egenskaben FirstName fra andre metoder i klassen. Du kan give set adgang eller privat tilgængelighed i stedet for intern eller offentlig:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Egenskaben FirstName kan læses fra en hvilken som helst kode, men den kan kun tildeles fra kode i klassen Person.
Du kan føje en hvilken som helst restriktiv adgangsændring til enten set eller get accessors. En adgangsmodifikator på en individuel accessor skal være mere restriktiv end egenskabens adgang. Den foregående kode er juridisk, fordi egenskaben FirstName er public, men den set accessor er private. Du kunne ikke deklarere en private egenskab med en public accessor. Egenskabserklæringer kan også erklæres protected, internal, protected internaleller endda private.
Der er to særlige adgangsmodifikatorer til set accessors:
- En
setaccessor kan haveinitsom adgangsændring. Dennesetaccessor kan kun kaldes fra en objektinitialiseringsfunktion eller typens konstruktører. Det er mere restriktivt endprivatepå densetaccessor. - En automatisk implementeret egenskab kan deklarere en
getaccessor uden ensetaccessor. I dette tilfælde tillader compileren, at densetaccessor kun kaldes fra typens konstruktører. Det er mere restriktivt endinit-accessoren på densetaccessor.
Overvej følgende opdateringer til klassen Person:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
I det foregående eksempel kræves det, at kaldere bruger den konstruktør, der indeholder parameteren FirstName. Opkaldere kan ikke bruge objektinitialisering til at tildele en værdi til egenskaben. Hvis du vil understøtte initialiseringsfunktionen, kan du gøre den set accessor til en init accessor, som vist i følgende kode:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Disse modifikatorer bruges ofte sammen med required modifikator til at gennemtvinge korrekt initialisering.
Begræns tilgængelighed for accessor
I nogle tilfælde er det nyttigt at begrænse adgangen til enten get eller set accessor. Du begrænser typisk tilgængeligheden af den set accessor, samtidig med at get-adgangsgiveren bevares offentligt tilgængelig.
For eksempel:
private string _name = "Hello";
public string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
I dette eksempel definerer en egenskab, der kaldes Name en get og set accessor. Den get accessor modtager tilgængelighedsniveauet for selve egenskaben, public i dette tilfælde, mens den set accessor udtrykkeligt begrænses ved at anvende protected adgangsændring på selve accessoren.
Begrænsninger for adgangsmodifikatorer for accessors
Brug af accessor-modifikatorer på egenskaber eller indeksering er underlagt disse betingelser:
- Du kan kun bruge accessor-modifikatorer, hvis egenskaben har både
setoggetaccessors. I dette tilfælde er modifikatoren kun tilladt for den ene af de to adgangsbrugere. - Tilgængelighedsniveauet på accessoren skal være mere restriktivt end tilgængelighedsniveauet for selve egenskaben eller indekseringsprogrammet.
Skrivebeskyttede statiske egenskaber
I følgende eksempel vises brugen af forekomst og statiske egenskaber i en klasse.
Klassen Employee har en statisk egenskab med navnet Counter, der sporer antallet af oprettede klasseforekomster. Egenskaben Counter er skrivebeskyttet, hvilket betyder, at der er adgang til den uden for klassen, men den kan ikke ændres. Egenskaben Counter er også static, hvilket betyder, at du får adgang til den Counter værdi ved hjælp af klassen Employee, ikke de employee1 eller employee2 forekomster af klassen.
public class Employee
{
public static int NumberOfEmployees;
private static int _counter;
private string _name;
// A read-write instance property:
public string Name
{
get => _name;
set => _name = value;
}
// A read-only static property:
public static int Counter => _counter;
// A Constructor:
public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}
public class Program
{
static void Main(string[] args)
{
// Create an initial instance of the Employee class
Employee employee1 = new Employee { Name = "NameOne" };
// Display the name and counter values
Console.WriteLine($"Employee 1: Name = {employee1.Name}, Counter = {Employee.Counter}");
// Create a second instance of the Employee class
Employee employee2 = new Employee { Name = "NameTwo" };
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
employee2.Name = "NameThree";
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Klassen Employee har følgende medlemmer:
-
NumberOfEmployees: Et offentligt statisk felt, der holder styr på det samlede antal oprettede medarbejderforekomster. Når den er statisk, deles den mellem alle forekomster af medarbejderklassen. -
_counter: Et privat statisk felt, der bruges til at tildele et entydigt tal til hver forekomst af Employee. Det deles også mellem alle forekomster. -
_name: Et felt til private forekomster, der gemmer navnet på medarbejderen. Den er specifik for hver forekomst af medarbejderklassen. -
Name: En offentlig egenskab for en forekomst af typen med læse- og skriveadgang, der giver adgang til feltet _name. Denget-accessor returnerer værdien af_name, og densetaccessor tildeler en ny værdi til_name. -
Counter: En offentlig skrivebeskyttet statisk egenskab, der giver adgang til feltet_counter. Denget-accessor returnerer værdien af_counter. EgenskabenCounterer knyttet til klassen i stedet for objekterne, fordi den er defineret som en statisk egenskab.
De to statiske felter initialiseres, når klassen først indlæses i hukommelsen, før der oprettes forekomster af klassen. I C#initialiseres statiske felter til deres standardværdier, hvis de ikke eksplicit initialiseres. For int felter er standardværdien 0.
Statiske egenskaber og felter tilhører selve klassen og ikke nogen bestemt forekomst af klassen. Alle forekomster af klassen deler de samme statiske egenskaber og felter.
Konstruktøren forøger det NumberOfEmployees statiske felt med 1 og tildeler den nye værdi til det _counter statiske felt. Denne fremgangsmåde sikrer, at hver Employee forekomst får et entydigt tal.
Private adgangsbrugere
Overvej følgende kode, der implementerer læse-/skriveegenskaber:
class Person
{
private string _name = "N/A";
private int _age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Set some values on the person object:
person.Name = "NameOne";
person.Age = 99;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Increment the Age property:
person.Age += 1;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = NameOne, Age = 99
Person details - Name = NameOne, Age = 100
*/
I dette eksempel indeholder klassen PersonName og Age egenskaber. Egenskaberne er offentlige, og de omfatter både get og set accessors. Offentlige accessors tillader alle objekter at læse og skrive disse egenskaber.
Nogle gange er det at udelukke en af accessors. Du kan udelade den set accessor for at gøre egenskaben skrivebeskyttet:
public string Name
{
get
{
return _name;
}
}
Alternativt kan du fremvise én accessor offentligt, men gøre den anden privat eller beskyttet.
public string Name
{
get
{
return _name;
}
private set
{
_name = value;
}
}