Access Modifiers
1. Description
Access modifiers are keywords that set the visibility or accessibility level of types (like classes) and members (like methods and properties). They are a key part of encapsulation in Object-Oriented Programming.
There are four primary access modifiers in C#:
public: The member is accessible from anywhere, without restrictions.private: The member is only accessible from within the same class.protected: The member is accessible from within the same class and from classes that derive from it.internal: The member is only accessible from within the same assembly (a project in Visual Studio).protected internal: A combination ofprotectedandinternal.
2. Why It Is Important
Access modifiers are crucial for creating robust and maintainable code. They allow you to:
- Enforce Encapsulation: By hiding the internal implementation details of a class (
privatemembers) and exposing only what is necessary (publicmembers), you create a clear boundary. This prevents other parts of the code from depending on implementation details that might change. - Improve Security: You can prevent unauthorized access to sensitive data or critical methods.
- Create Clear APIs:
publicmembers form the public contract of your class. This makes it easier for other developers to understand how to use your class correctly.
3. Real-World Examples
- A
BankAccountclass would have apublicDeposit()method and apublicWithdraw()method. However, thebalancefield would beprivateto prevent direct modification from outside the class. The only way to change the balance is through the public methods, which can enforce rules (like not allowing a negative balance). - A base class might have a
protectedhelper method that is intended for use by its subclasses but not by the general public. - A library project might use the
internalmodifier for utility classes that are only meant to be used within the library itself and not exposed to the applications that use the library.
4. Syntax & Explanation
using System;
public class BankAccount
{
// 'private' field: Can only be accessed by code inside this class.
private decimal balance;
// 'public' constructor: Can be called from anywhere.
public BankAccount(decimal initialBalance)
{
balance = initialBalance;
}
// 'public' method: Part of the class's public API.
public void Deposit(decimal amount)
{
if (amount > 0)
{
balance += amount;
}
}
// 'public' method.
public void Withdraw(decimal amount)
{
if (amount > 0 && amount <= balance)
{
balance -= amount;
}
}
// 'public' method to get the current balance without allowing direct modification.
public decimal GetBalance()
{
return balance;
}
// 'private' helper method: Not accessible from outside.
private void LogTransaction(string message)
{
Console.WriteLine($"[LOG]: {message}");
}
}
class Program
{
static void Main()
{
var account = new BankAccount(100);
// These are allowed because the methods are public
account.Deposit(50);
account.Withdraw(20);
// This would cause a compile error because 'balance' is private
// account.balance = 1000000;
Console.WriteLine($"Current Balance: {account.GetBalance()}");
}
}
5. Use Cases
- Hiding Implementation Details: Use
privatefor any fields or methods that are not essential for the outside world to know about. This is the default level of encapsulation and should be your starting point. - Creating Public APIs: Use
publicfor the methods, properties, and constructors that you want to expose to other parts of your application or to other developers. - Extensibility for Subclasses: Use
protectedwhen you want to provide a hook for subclasses to extend or modify the behavior of your class, without making it public to everyone.
6. Mini Practice Task
- Create a
Personclass. - Add a
privatefield for_age. - Add a
publicmethodSetAge(int age)that sets the_agefield, but only if the provided age is between 0 and 120. - Add a
publicmethodGetAge()that returns the value of the_agefield. - In your
Mainmethod, create aPersonobject and try to set a valid age and an invalid age, and print the result.