Åtkomstmodifierare förklarade
↑Exemplen är oberoende C#-utdrag för moderna .NET-konsolprojekt, om inget annat anges. Klassdeklarationer och toppnivåkod kan placeras i samma Program.cs-fil, med toppnivåkoden först.
Snabböversikt
Section titled “Snabböversikt”Åtkomst avgör vilken kod som får använda en typ eller medlem. Börja med den minsta åtkomstnivå som passar behovet och utöka bara när det behövs.
Interaktiv åtkomstmatris
Section titled “Interaktiv åtkomstmatris”Endast den innehållande typen (särskilda regler gäller nästlade typer).
| Modifierare | Inuti klassen | Härledd, samma assembly | Annan, samma assembly | Härledd, annan assembly | Annan, annan assembly |
|---|---|---|---|---|---|
public | |||||
private | |||||
protected | |||||
internal | |||||
protected internal | |||||
private protected |
Matrisen visar typiska åtkomstfall för klassmedlemmar. En medlem kan aldrig vara mer tillgänglig än sin klass. För protected finns särskilda regler kring vilken referens som används. file gäller i stället toppnivåtyper i samma källkodsfil.
Så fungerar det
Section titled “Så fungerar det”Public jämfört med private
Section titled “Public jämfört med private”public ger åtkomst där den omgivande typen är tillgänglig. private begränsar åtkomsten till den innehållande typen (med särskilda regler för nästlade typer). Privata implementationer kan ändras utan att anropare påverkas.
Counter counter = new();counter.Increment();Console.WriteLine(counter.Value);// counter.count = 5; // compiler error
public class Counter{ private int count; public int Value => count; public void Increment() => count++;}Protected och internal
Section titled “Protected och internal”protected ger åtkomst inifrån klassen och i härledda klasser. internal ger åtkomst inom samma assembly. I Unity skapar assembly-definitioner (.asmdef) gränser som påverkar internal. En namnrymd är inte en assembly.
public class Enemy{ protected int health = 100; internal void ResetHealth() => health = 100;}public class Boss : Enemy{ public void Damage() => health -= 10;}Kombinerade modifierare och fil-lokala typer
Section titled “Kombinerade modifierare och fil-lokala typer”protected internal betyder samma assembly ELLER en härledd typ i en annan assembly. private protected begränsar härledda typer till samma assembly (utöver innehållande typ). file gäller tillåtna toppnivåtyper i samma källkodsfil. Alla modifierare passar inte alla deklarationer.
public class Base{ protected internal void ExtendOrUseLocally() { } private protected void ExtendWithinAssembly() { }}file sealed class FileOnlyHelper { }Fördjupning: utforma en tydlig API-gräns
Section titled “Fördjupning: utforma en tydlig API-gräns”Åtkomst styr vilken kod som får använda en medlem
Section titled “Åtkomst styr vilken kod som får använda en medlem”En åtkomstmodifierare är inte en säkerhetsgräns mot opålitliga program. Det är en regel som kompilatorn kontrollerar och som hjälper dig att skydda objektets tillstånd. Börja gärna med private: då kan du ändra implementationen utan att anropande kod påverkas. Öppna endast det andra delar av programmet behöver.
Tänk på ett bankkonto: om annan kod fritt fick skriva till Balance kunde saldot bli negativt. En publik metod kan tillåta en kontrollerad operation medan fältets logik skyddas.
var account = new Account(100);account.Withdraw(30);Console.WriteLine(account.Balance); // 70
public sealed class Account{ public decimal Balance { get; private set; } public Account(decimal openingBalance) => Balance = openingBalance;
public void Withdraw(decimal amount) { if (amount <= 0 || amount > Balance) throw new ArgumentOutOfRangeException(nameof(amount)); Balance -= amount; }}protected skapar avsiktliga utökningspunkter
Section titled “protected skapar avsiktliga utökningspunkter”En protected-medlem kan användas från härledda typer. Använd den när underklasser behöver en definierad funktion, inte för att öppna alla fält. En protected metod eller egenskap är ofta bättre än ett fritt ändringsbart fält. En härledd klass kan finnas i en annan assembly om basklassen är tillgänglig där.
Assembly och namespace är olika saker
Section titled “Assembly och namespace är olika saker”internal ger åtkomst inom samma assembly, exempelvis en .dll eller ett projekt som kompileras till en assembly. Två klasser i samma namespace får inte automatiskt åtkomst över assembly-gränser. I Unity påverkar .asmdef-filer dessa gränser. Om du delar upp koden i fler assemblies kan nya åtkomstfel därför uppstå.
Kombinerade modifierare
Section titled “Kombinerade modifierare”protected internal: tillgänglig inom samma assembly ELLER från härledda klasser i andra assemblies.private protected: tillgänglig i den innehållande typen och från härledda klasser inom samma assembly.file: kan användas för vissa toppnivåtyper och begränsar typen till aktuell källfil; det är inte en modifierare för vanliga fält.
Tänk på protected internal som en union och private protected som ett snitt (med åtkomst inifrån den innehållande typen). Använd inte public bara för att kringgå ett designproblem.
Den omgivande typen sätter också gränser
Section titled “Den omgivande typen sätter också gränser”En public-medlem i en internal klass gör inte klassen publik utanför sin assembly. En publik metod kan normalt inte heller exponera en mindre tillgänglig typ i sin signatur; kompilatorn rapporterar då inkonsekvent åtkomst. Toppnivåtyper utan modifierare är normalt internal, medan medlemmar i klasser normalt är private.
Välj efter behov
Section titled “Välj efter behov”| Du vill… | Börja med… | Varför? |
|---|---|---|
| Dölja implementationsdetaljer | private |
Förändringar stannar i klassen |
| Ge andra en stabil API-yta | public |
Visar vilka operationer som stöds |
| Dela implementation inom projektet | internal |
Minskar beroenden utifrån |
| Låta underklasser anpassa beteenden | protected metod |
Tydlig utökningspunkt |
| Ge åtkomst internt eller för externa underklasser | protected internal |
Förening av målgrupperna |
| Ge underklasser åtkomst endast i samma assembly | private protected |
Mindre arvsyta |
När och varför?
Section titled “När och varför?”Använd private för implementation, public för avsedda API:er, internal inom samma assembly och protected när arv verkligen ska kunna använda medlemmen.
Vanligt misstag
Section titled “Vanligt misstag”Åtkomstmodifierare är kompilatorregler, inte säkerhetsgränser. protected internal är ELLER, medan private protected begränsas till samma assembly.
Testa själv
Section titled “Testa själv”Välj modifierare för en hjälpmetod som används endast inuti sin klass och för typer som delas endast inom en Unity-asmdef.
Visa ett lösningsförslag
private för hjälpmetoden och internal för typen inom samma assembly.
