Encapsulation and Properties in C#: Access Modifiers & Getters/Setters

1. Encapsulation and Properties Overview

Q: What is encapsulation in C#?

Encapsulation is an object-oriented programming principle that bundles data (fields) and methods within a class, controlling access to protect the data's integrity. In C#, encapsulation is achieved using access modifiers and properties to hide implementation details and expose only necessary interfaces.

Q: What are properties in C#?

Properties are special members of a class that provide controlled access to private fields using getter (get) and setter (set) methods. They act as an interface to read or modify data while enforcing validation or logic, supporting encapsulation.

Syntax:

public type PropertyName { get; set; } // Auto-implemented property
// OR
public type PropertyName {
    get { return field; }
    set { field = value; } // value is implicit parameter
}

Q: Why is encapsulation important?

Q: How does encapsulation in C# differ from C/C++?

2. Access Modifiers

Q: What are access modifiers in C#?

Access modifiers control the visibility and accessibility of class members (fields, properties, methods). C# provides:

Q: How are access modifiers used in encapsulation?

Access modifiers hide internal data (e.g., private fields) and expose controlled interfaces (e.g., public properties or methods), ensuring encapsulation by restricting direct access to sensitive data.

Q: Can you give an example of encapsulation with access modifiers?

using System;

namespace Encapsulation
{
    class BankAccount
    {
        // Private field
        private decimal balance;

        // Public property with validation
        public decimal Balance
        {
            get { return balance; }
            set
            {
                if (value >= 0)
                    balance = value;
                else
                    throw new ArgumentException("Balance cannot be negative");
            }
        }

        // Protected method (accessible in derived classes)
        protected void LogTransaction(string type, decimal amount)
        {
            Console.WriteLine($"{type}: {amount:C}");
        }

        // Public method
        public void Deposit(decimal amount)
        {
            if (amount > 0)
            {
                Balance += amount;
                LogTransaction("Deposit", amount);
            }
            else
            {
                throw new ArgumentException("Deposit amount must be positive");
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BankAccount account = new BankAccount();
            account.Deposit(100.50m);
            Console.WriteLine($"Current Balance: {account.Balance:C}");
            // account.balance = -50; // Error: balance is private
        }
    }
}

Output:

Deposit: $100.50
Current Balance: $100.50

3. Getters and Setters (Properties)

Q: What are getters and setters in C#?

Getters and setters are the get and set accessors of a property, controlling how a field is read or modified:

Q: What are the types of properties in C#?

Q: How do properties improve over traditional getter/setter methods?

Properties provide a cleaner syntax, integrate with C#'s type system, and support modern features like auto-implementation and expression-bodied properties, making code more concise and maintainable compared to explicit getter/setter methods in C++ or Java.

Q: Can you give an example of properties with getters and setters in C#?

using System;

namespace Properties
{
    class Employee
    {
        private string name;
        private int salary;

        // Auto-implemented property
        public string Department { get; set; }

        // Property with validation
        public string Name
        {
            get => name; // Expression-bodied getter
            set => name = string.IsNullOrEmpty(value) ? "Unknown" : value;
        }

        // Read-only property
        public int Salary
        {
            get => salary;
            private set => salary = value >= 0 ? value : 0; // Private setter
        }

        // Init-only property (C# 9.0+)
        public int Id { get; init; }

        public Employee(string name, int salary, int id)
        {
            Name = name;
            Salary = salary; // Uses private setter
            Id = id;
        }

        public void GiveRaise(int amount)
        {
            Salary += amount; // Uses private setter
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Object creation with init-only property
            Employee emp = new Employee("Krishna", 50000, 101)
            {
                Department = "IT"
            };

            Console.WriteLine($"Employee: {emp.Name}, ID: {emp.Id}, Dept: {emp.Department}, Salary: {emp.Salary:C}");
            emp.GiveRaise(5000);
            Console.WriteLine($"After raise, Salary: {emp.Salary:C}");
            // emp.Id = 102; // Error: Id is init-only
            // emp.Salary = -100; // Error: Salary has private setter
        }
    }
}

Output:

Employee: Krishna, ID: 101, Dept: IT, Salary: $50,000.00
After raise, Salary: $55,000.00

Q: How do properties in C# differ from C/C++?

4. Common Mistakes & Best Practices

Q: Common mistakes?

Encapsulation:

Access Modifiers:

Properties:

Q: Best practices?

Encapsulation:

Access Modifiers:

Properties:

General: