Zrozumienie modyfikatorów dostępu w C#
W tym artykułe zagłębimy się w modyfikatory dostępu w C#, które definiują widoczność i dostępność typów, metod i zmiennych w C#. Tim Corey w swoim wideo "C# Access Modifiers (beyond public and private) - co to jest, jak je używać i najlepsze praktyki" wyjaśnia różne modyfikatory dostępu i demonstruje ich praktyczne zastosowanie w aplikacji konsolowej.
Ten artykuł wyjaśni to, co omówił Tim, wraz z przykładami kodu, aby zwiększyć zrozumieniuiuiuiuie. Podane znaczniki czasowe pozwalają śledzić wideo dla bardziej praktycznego doświadczenia.
Co to są modyfikatory dostępu?
Wprowadzenie
Tim Corey zaczyna od wprowadzenia do modyfikatorów dostępu, wyjaśniając, że określają one, kto może widzieć i używać zasobu w C#. Chociaż znamy powszechnie używane modyfikatory public i private, Tim bada sześć różnych modyfikatorów dostępu i ich zastosowania.
Demo aplikacji wyjaśnione
Tim konfiguruje prostą aplikację, aby zademonstrować, jak działają różne modyfikatory dostępu. Aplikacja składa się z interfejsu konsolowego i biblioteki demonstracyjnej, obie w .NET framework.
Struktura projektu:
- Console UI: Aplikacja konsolowa do testowania modyfikatorów dostępu.
- Biblioteka demo: Biblioteka klas, w której są demonstrowane różne modyfikatory dostępu.
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}
1. Private
Co to jest:
Modyfikator private ogranicza dostęp do metody, pola lub właściwości tylko wewnątrz klasy, w której jest zdefiniowana.
Przykład kodu:
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}
Wyjaśnienie: Metoda PrivateDemo jest dostępna tylko w obrębie klasy AccessDemo. W wideo Tim demonstruje, że nie można jej uzyskać z zewnątrz klasy, nawet jeśli inne klasy znajdują się w tym samym projekcie.
Najlepsza praktyka: Używaj private, gdy chcesz ograniczyć dostęp do wewnętrznych działań swojej klasy, zapewniając, że nie mogą być bezpośrednio zmienione z innych części aplikacji.
2. Internal
Co to jest:
Modyfikator internal pozwala na dostęp do metody lub właściwości tylko w tej samej asembli (projekcie). To szerszy zasięg niż modyfikator private, ponieważ obejmuje wszystkie klasy w tym samym projekcie.
Przykład kodu:
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}
Wyjaśnienie: Metoda InternalDemo może być dostępna przez dowolną klasę w tej samej asembli, ale nie z innych asembli. W wideo, Tim pokazuje, że internal pozwala na dostęp wewnątrz tego samego projektu, ale odmawia dostępu z zewnątrz.
Najlepsza praktyka: Używaj internal dla metod lub właściwości, które są przystosowane do użytku tylko wewnątrz bieżącej asembli, takich jak funkcje pomocnicze lub narzędzia, które nie powinny być narażone na dostęp z zewnętrznych projektów.
3. Public
Co to jest:
Modyfikator public pozwala na dostęp do metody lub właściwości z dowolnej innej klasy czy asembli. To najbardziej permissywna poziom dostępu.
Przykład kodu:
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}
Wyjaśnienie: Metoda PublicDemo jest dostępna z każdego miejsca, w tym innych klas w tej samej asembli lub innych asembli. Tim demonstruje, że public to najczęściej używany modyfikator dostępu, zwłaszcza przy wystawianiu metod w bibliotekach.
Najlepsza praktyka: Używaj public dla metod i właściwości, które muszą być dostępne przez inne części aplikacji lub zewnętrzne projekty, takie jak punkty końcowe API czy powszechnie używane narzędzia.
4. Protected
Co to jest:
Modyfikator protected pozwala na dostęp do metody lub właściwości wewnątrz klasy, w której jest zdefiniowana, oraz w dowolnych klasach dziedziczących (dziedziczenie). Ten modyfikator jest użyteczny w programowaniu obiektowym, zwłaszcza w przypadkach dziedziczenia.
Przykład kodu:
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}
Wyjaśnienie: Metoda ProtectedDemo może być dostępna z klasy AccessDemo i dowolnej klasy, która od niej dziedziczy. Tim wyjaśnia, że protected jest mniej powszechny, ale bardzo przydatny przy pracy z dziedziczeniem.
Najlepsza praktyka: Używaj protected, gdy chcesz pozwolić klasom dziedziczącym mieć dostęp do specyficznych metod lub właściwości, ale nie chcesz, aby były one dostępne poza hierarchią klas.
5. Private Protected
Co to jest:
Modyfikator private protected łączy zasady private i protected. Ogranicza dostęp do metod lub właściwości wewnątrz definiującej klasy i klas dziedziczących w tej samej asembli. Oznacza to, że oferuje to dalszy poziom ochrony i ściślejszą granicę dla kontroli dostępu opartego na dziedziczeniu w porównaniu z protected.
Przykład kodu:
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}
Wyjaśnienie: Metoda PrivateProtectedDemo jest dostępna w DerivedClass, ponieważ dziedziczy z AccessDemo i istnieje w tej samej asembli. Jednak nie można jej uzyskać w UnrelatedClass, ponieważ ta klasa nie dziedziczy z AccessDemo.
Najlepsza praktyka: Używaj modyfikatora dostępu private protected oszczędnie, gdy trzeba ściśle kontrolować dostęp dziedziczenia w tej samej asembli. To jest szczególnie użyteczne w scenariuszach, w których ujawnienie metod lub właściwości przez asembli może zagrozić enkapsulacji.
6. Protected Internal
Co to jest:
Modyfikator protected internal łączy poziomy dostępu protected i internal. Pozwala na dostęp z tej samej asembli lub z klas dziedziczących, nawet jeśli są w innej asembli.
Przykład kodu:
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}
Wyjaśnienie: Metoda ProtectedInternalDemo jest dostępna z tej samej asembli oraz z dowolnej klasy dziedziczącej, niezależnie od asembli.
Najlepsza praktyka: Używaj protected internal, gdy chcesz ujawnić metodę zarówno klasom dziedziczącym (w innych asembli), jak i klasom w tej samej asembli, ale nie dla wszystkich.
Dłączego nie zrobić wszystkiego publicznym?
Tim Corey wyjaśnia znaczenie używania modyfikatorów dostępu i dłączego wszystko nie powinno być po prostu publiczne. Chociaż zrobienie wszystkiego publicznym może wydawać się wygodne, wprowadza znaczące zagrożenia, w tym wycieki danych, błędy i zamieszanie w rozwijaniu oprogramowania. Modyfikatory dostępu istnieją, aby zabezpieczyć informacje, zapobiegać niezamierzonemu publicznemu dostępowi i zapewniać przejrzystość w bazach kodu.
1. Ochrona prywatnych informacji
Tim omawia, dłączego poufne informacje, takie jak numery ubezpieczenia społecznego (SSN) lub numery kart kredytowych, nie powinny być publiczne. Demonstruje "zły przykład" klasy, gdzie dochodzi do ujawnienia danych z powodu publicznego dostępu:
Zły przykład:
public class User
{
public string SSN; // Anyone can access and modify it directly
}
public class User
{
public string SSN; // Anyone can access and modify it directly
}
Dobry przykład:
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}
2. Zabezpieczanie prywatnych metod
Rozpoczęcie: 35:11\
Tim wyjaśnia, że prywatne metody pomagają w enkapsulacji zachowań, które nie powinny być bezpośrednio dostępne. Używa przykładu metody DeleteUser jako części większego procesu, takiego jak rozłącznie pracownika.
Zły przykład:
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}
Dobry przykład:
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}
3. Zapobieganie błędom
Modyfikatory dostępu zapobiegają błędom, zapewniając, że dane są ustawiane lub uzyskiwane z odpowiednią walidacją. Tim ilustruje to przykładem obejmującym właściwość Age.
Zły przykład:
public class Person
{
public int Age; // Can be directly set to an invalid value
}
public class Person
{
public int Age; // Can be directly set to an invalid value
}
Dobry przykład:
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}
4. Zmniejszenie zamieszania i zwiększenie przejrzystości
Prawidłowe użycie modyfikatorów dostępu upraszcza rozwój poprzez ujawnianie tylko tego, co konieczne, unikając zamieszania. Na przykład, w aplikacji z tysiącami metod ujawnienie tylko tych publicznych zapewnia, że deweloperzy widzą tylko istotne opcje.
Przykład:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
5. Korzyści w większych aplikacjach lub bibliotekach
Dla projektów na dużą skalę Tim wyjaśnia, jak właściwe użycie modyfikatorów dostępu zapewnia, że tylko wymagańe części biblioteki są ujawnione, zmniejszając obciążenie poznawcze u deweloperów korzystających z biblioteki.
Przykład:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
Poprzez właściwe użycie tych modyfikatorów dostępu, ułatwiasz swoją pracę i pracę kolejnej osoby.
Wnioski
Tim Corey dostarcza jasny i praktyczny przewodnik po opanowaniu modyfikatorów dostępu w C#, pokazując, jak skutecznie je używać do tworzenia bezpiecznych, łatwych w utrzymaniu i profesjonalnych aplikacji. Jego szczegółowe wyjaśnienia i przykłady z życia codziennego czynią ten temat dostępnym dla programistów na wszystkich poziomach.
Aby uzyskać bardziej dogłębne spojrzenie i zobaczyć te pojęcia w akcji, koniecznie obejrzyj pełne wideo Tima i zbadj jego kanał dla cennych treści na temat C# i innych tematów programistycznych. To obowiązkowe źródło dla każdego, kto poważnie myśli o poprawie swoich umiejętności programistycznych!
