Hoppa till innehåll

Å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.

Å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.

Endast den innehållande typen (särskilda regler gäller nästlade typer).

ModifierareInuti klassenHärledd, samma assemblyAnnan, samma assemblyHärledd, annan assemblyAnnan, 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.

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.

Example.cs
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 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.

Example.cs
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.

Example.cs
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.

Program.cs
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.

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å.

  • 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.

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

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.

Åtkomstmodifierare är kompilatorregler, inte säkerhetsgränser. protected internal är ELLER, medan private protected begränsas till samma assembly.

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.