404 Not Found

404 Not Found


nginx

Access Modifiers and Properties

Access Modifiers

Access modifiers control the accessibility of class members and are the core mechanism for encapsulation. C# provides six access levels:

Modifier Same Class Subclass (Same Assembly) Subclass (Different Assembly) Same Assembly Different Assembly
public
private
protected
internal
protected internal
private protected
💡 protected internal is an "OR" relationship: subclasses or same assembly can access. private protected is an "AND" relationship: must be both a subclass and in the same assembly.

Example

CSHARP
public class Animal
{
    public string Species;
    private int health;
    protected int energy;
    internal string category;

    public void ShowInfo()
    {
        Console.WriteLine($"Species: {Species}, Health: {health}, Energy: {energy}, Category: {category}");
    }

    public void SetHealth(int h) { health = h; }
}

public class Dog : Animal
{
    public void Run()
    {
        energy -= 10;
        category = "Mammal";
    }
}
▶ Try it Yourself
TEXT
Species: Dog, Health: 100, Energy: 90, Category: Mammal

Encapsulation Principles

Encapsulation requires setting fields to private and controlling read/write access through public properties, preventing external code from directly modifying internal data.

Example

CSHARP
public class BankAccount
{
    private decimal balance;

    public decimal Balance
    {
        get { return balance; }
        set
        {
            if (value < 0)
                throw new ArgumentException("Balance cannot be negative");
            balance = value;
        }
    }
}
▶ Try it Yourself
CSHARP
var account = new BankAccount();
account.Balance = 1000m;
Console.WriteLine($"Balance: {account.Balance}");
TEXT
Balance: 1000
⚠️ Making fields public directly breaks encapsulation and prevents adding validation logic later. Always use private fields + public properties.

Properties

Properties are safe wrappers for fields, controlling read/write logic through get and set accessors. value is the implicit parameter of the set accessor, representing the value assigned by the caller.

Example

CSHARP
public class Student
{
    private string name;

    public string Name
    {
        get { return name; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("Name cannot be empty");
            name = value;
        }
    }
}
▶ Try it Yourself
CSHARP
var s = new Student();
s.Name = "Alice";
Console.WriteLine(s.Name);
TEXT
Alice

Auto-Properties

When no additional logic is needed, use auto-properties { get; set; }, where the compiler automatically generates a hidden backing field.

Example

CSHARP
public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}
▶ Try it Yourself
CSHARP
var p = new Product { Name = "Pen", Price = 2.5m };
Console.WriteLine($"{p.Name}: ${p.Price}");
TEXT
Pen: $2.5
📌 Auto-properties reduce boilerplate code. When validation is needed, they can be expanded into full properties at any time without affecting callers.

The init Accessor (C# 9)

The init accessor allows a property to be assigned during object initialization, after which it becomes read-only, enabling immutable objects.

Example

CSHARP
public class Config
{
    public string Host { get; init; }
    public int Port { get; init; }
}
▶ Try it Yourself
CSHARP
var cfg = new Config { Host = "localhost", Port = 8080 };
Console.WriteLine($"{cfg.Host}:{cfg.Port}");
TEXT
localhost:8080
⚠️ Assigning a value after initialization causes a compile error: cfg.Port = 9090; is illegal.

Read-Only Properties

A property with only get is a read-only property. Its value can only be assigned in the constructor through the backing field.

Example

CSHARP
public class Circle
{
    public double Radius { get; }

    public Circle(double radius)
    {
        Radius = radius;
    }
}
▶ Try it Yourself
CSHARP
var c = new Circle(5.0);
Console.WriteLine($"Radius: {c.Radius}");
TEXT
Radius: 5

Computed Properties

Computed properties have no backing field. They dynamically calculate and return values using expression-bodied members =>, without storing data.

Example

CSHARP
public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area => Width * Height;
    public double Perimeter => 2 * (Width + Height);
}
▶ Try it Yourself
CSHARP
var r = new Rectangle { Width = 3, Height = 4 };
Console.WriteLine($"Area: {r.Area}, Perimeter: {r.Perimeter}");
TEXT
Area: 12, Perimeter: 14

The required Modifier (C# 11)

The required modifier forces callers to assign a value to the property during initialization, otherwise a compile error occurs.

Example

CSHARP
public class User
{
    public required string Name { get; init; }
    public required string Email { get; init; }
    public int Age { get; init; }
}
▶ Try it Yourself
CSHARP
var u = new User { Name = "Bob", Email = "bob@test.com" };
Console.WriteLine($"{u.Name} ({u.Email})");
TEXT
Bob (bob@test.com)
💡 required is typically paired with init to ensure required fields of immutable objects are not missed.

Introduction to Records

record is a reference type introduced in C# 9 that natively supports immutability and value-based equality, making it ideal for pure data objects.

Example

CSHARP
public record Person(string Name, int Age);
▶ Try it Yourself
CSHARP
var p1 = new Person("Alice", 30);
var p2 = new Person("Alice", 30);
Console.WriteLine($"Equal: {p1 == p2}");
Console.WriteLine(p1);
TEXT
Equal: True
Person { Name = Alice, Age = 30 }
🔥 The record's parameter list automatically generates init read-only properties, and == compares by value rather than reference. This will be covered in depth in later lessons.

❓ FAQ

Q What is the difference between protected internal and private protected?
A protected internal is an "OR" relationship (accessible by subclasses or same assembly), private protected is an "AND" relationship (must be both a subclass and in the same assembly).
Q What is the difference between auto-properties and public fields?
A Auto-properties have a backing field, can be expanded to add logic at any time, support interface implementation and data binding, which public fields cannot do.
Q What is the difference between init and set?
A set can be assigned at any time, init can only be assigned during object initialization (constructor or object initializer), after which it is read-only.
Q Can a read-only property { get; } be assigned outside the constructor?
A No. It can only be assigned in the constructor through the backing field, and cannot be modified afterwards.
Q What is the core difference between record and class?
A record compares equality by value by default, supports the with expression for creating copies, and is suited for immutable data; class compares by reference.

📖 Summary

📝 Exercises

  1. Create a Temperature class with a celsius field set to private, use the Celsius property's set accessor to limit the temperature to no less than -273.15, and provide a Fahrenheit computed property that returns the converted value
  2. Create a Book class using auto-properties (Title, Author, Price), add non-negative validation in Price's set (hint: expand into a full property)
  3. Define a ServerConfig class where Host and Port use init accessors and are marked as required, try modifying after initialization and observe the compile error
  4. Define Point(double X, double Y) using record, create two instances with the same coordinates, verify that == comparison returns True
  5. Create an Employee class with Id as a read-only property (assigned in constructor), Name using required init, Salary using a set property with validation, and AnnualSalary as a computed property
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏