Begrense tilgang til egenskaper
En klasse kan angi hvor tilgjengelig hvert av medlemmene er for kode utenfor klassen. Metoder og variabler som ikke er ment å brukes fra utenfor klassen eller samlingen, kan skjules for å begrense potensialet for kodefeil eller skadelige utnyttelser.
Noen metoder og egenskaper er ment å kalles eller åpnes fra kode utenfor en klasse, kjent som klientkode. Andre metoder og egenskaper kan bare brukes i selve klassen. Det er viktig å begrense tilgjengeligheten til koden slik at bare den tiltenkte klientkoden kan nå den. Du angir hvor tilgjengelige typene og medlemmene deres er for klientkode ved hjelp av følgende tilgangsmodifiserte:
-
public: Typen eller medlemmet er tilgjengelig med en annen kode i samme samling eller en annen samling som refererer til den. -
protected: Typen eller medlemmet er bare tilgjengelig med kode i samme klasse eller en avledet klasse. -
internal: Typen eller medlemmet er tilgjengelig med en kode i samme samling, men ikke fra en annen samling. -
protected internal: Typen eller medlemmet er tilgjengelig med en kode i samme samling, eller av en hvilken som helst avledet klasse i en annen samling. -
private: Typen eller medlemmet er bare tilgjengelig med kode i samme klasse eller struktur. -
private protected: Typen eller medlemmet er bare tilgjengelig med kode i samme samling, og bare etter kode i samme klasse eller en avledet klasse.
Klassemedlemmer tilordnes private tilgang som standard.
Få tilgang til modifikatorer på egenskaper og tilgangsmenn
Frem til dette punktet i modulen fokuserte vi på egenskaper som inkluderer både get- og set-tilgangsmenn. Disse egenskapene kalles lese-skriveegenskaper. I tillegg til lese- og skriveegenskaper kan du opprette skrivebeskyttede egenskaper eller gi forskjellig tilgjengelighet til set og get-tilgangskontrollører.
Som standard har get og set-tilgangstakere samme tilgjengelighetsnivå som egenskapen de tilhører. Du kan imidlertid begrense tilgjengeligheten til enten get eller set accessor. Access-modifikatorer er nyttige når du vil begrense tilgangen til selve egenskapen, men likevel gi tilgang til egenskapens verdi gjennom en get-tilgangsør.
La oss si at du har en Person klasse som bare skal aktivere endring av verdien for FirstName-egenskapen fra andre metoder i klassen. Du kan gi set tilgangsperson privat tilgjengelighet i stedet for intern eller offentlig:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Egenskapen FirstName kan leses fra en hvilken som helst kode, men den kan bare tilordnes fra kode i Person-klassen.
Du kan legge til en hvilken som helst restriktiv tilgangsendring i enten set eller get-tilgangstakere. En tilgangsendring på en individuell tilgangsperson må være mer restriktiv enn tilgangen til egenskapen. Den forrige koden er lovlig fordi egenskapen FirstName er public, men set-tilgangsøren er private. Du kan ikke erklære en private egenskap med en public-tilgangsør. Egenskapsdeklarasjoner kan også deklareres protected, internal, protected internaleller til og med private.
Det finnes to spesielle tilgangsmodifiserte for set-tilbehør:
- En
setaccessor kan hainitsom tilgangsendring. Dennesetaccessor kan bare kalles fra en objektinitialiserer eller konstruktøren av typen. Det er mer restriktivt ennprivatepå densettiltrederen. - En automatisk implementert egenskap kan deklarere en
gettiltreder uten ensetaccessor. I så fall tillater kompilatoren atset-tiltrederen bare kan kalles fra konstruktøren av typen. Det er mer restriktivt enninit-tiltrederen påset-tilgangsøren.
Vurder følgende oppdateringer til Person-klassen:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
Det foregående eksemplet krever at innringere bruker konstruktøren som inneholder FirstName-parameteren. Innringere kan ikke bruke objektinitialiserere til å tilordne en verdi til egenskapen. Hvis du vil støtte initialiserere, kan du gjøre set-tiltrederen til en init tiltreder, 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 modifikatorene brukes ofte med required modifikator for å fremtvinge riktig initialisering.
Begrens tilgjengelighet for tilgangstilgang
I noen tilfeller er det nyttig å begrense tilgangen til enten get eller set accessor. Vanligvis begrenser du tilgjengeligheten til set-tilgangsøren, samtidig som du holder get-tilgangsøren offentlig tilgjengelig.
For eksempel:
private string _name = "Hello";
public string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
I dette eksemplet definerer en egenskap kalt Name en get- og set-tilgangsør. Den get adkomstøren mottar tilgjengelighetsnivået for selve egenskapen, public i dette tilfellet, mens set-tilgangsøren er eksplisitt begrenset ved å bruke protected tilgangsendring på selve tilgangsvelgeren.
Begrensninger for tilgangsmodifiserere på tilgangsbesparede
Bruk av endring av tilgangsobjekter på egenskaper eller indekserere er underlagt disse betingelsene:
- Du kan bare bruke endring av tilgangsbeskyttere hvis egenskapen har både
set- ogget-tilgangstakere. I dette tilfellet er modifikatoren bare tillatt på én av de to tilgangsmennene. - Tilgjengelighetsnivået på accessoren må være mer restriktivt enn tilgjengelighetsnivået på selve egenskapen eller indeksereren.
Skrivebeskyttede statiske egenskaper
Eksemplet nedenfor viser bruken av forekomster og statiske egenskaper i en klasse.
Klassen Employee har en statisk egenskap med navnet Counter som sporer antallet klasseforekomster som er opprettet. Egenskapen Counter er skrivebeskyttet, noe som betyr at den kan åpnes utenfor klassen, men ikke endres. Egenskapen Counter er også static, noe som betyr at du får tilgang til Counter-verdien ved hjelp av Employee klassen, ikke employee1 eller employee2 forekomster av 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 offentlig statisk felt som holder oversikt over det totale antallet ansattforekomster som er opprettet. Den er statisk, og deles mellom alle forekomster av Ansatt-klassen. -
_counter: Et privat statisk felt som brukes til å tilordne et unikt nummer til hver ansattforekomst. Den deles også mellom alle forekomster. -
_name: Et privat forekomstfelt som lagrer navnet på den ansatte. Det er spesifikt for hver forekomst av Ansatt-klassen. -
Name: En offentlig skriveforekomstegenskap som gir tilgang til _name-feltet. Accessorengetreturnerer verdien for_name, ogsettildeler en ny verdi til_name. -
Counter: En offentlig, skrivebeskyttet statisk egenskap som gir tilgang til_counter-feltet. Accessorengetreturnerer verdien for_counter. EgenskapenCounterer knyttet til klassen i stedet for objektene fordi den er definert som en statisk egenskap.
De to statiske feltene initialiseres når klassen først lastes inn i minnet, før noen forekomster av klassen opprettes. I C#initialiseres statiske felt til standardverdiene hvis de ikke er eksplisitt initialisert. For int felt er standardverdien 0.
Statiske egenskaper og felt tilhører selve klassen, ikke til en bestemt forekomst av klassen. Alle forekomster av klassen deler de samme statiske egenskapene og feltene.
Konstruktøren øker NumberOfEmployees statisk felt med 1 og tilordner den nye verdien til det _counter statiske feltet. Denne fremgangsmåten sikrer at hver Employee forekomst får et unikt tall.
Private tilgangspersoner
Vurder følgende kode som implementerer lese-skriveegenskaper:
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 eksemplet inneholder Person klassen Name og Age egenskaper. Egenskapene er offentlige, og de inkluderer begge get og set tilgangsmenn. Offentlige tilgangstakere tillater at alle objekter kan lese og skrive disse egenskapene.
Noen ganger er det å ekskludere én av tilgangsmennene. Du kan utelate set-tilgangsøren for å gjøre egenskapen skrivebeskyttet:
public string Name
{
get
{
return _name;
}
}
Alternativt kan du eksponere én tiltreder offentlig, men gjøre den andre privat eller beskyttet.
public string Name
{
get
{
return _name;
}
private set
{
_name = value;
}
}