类的基本结构

public class Person
{
    // 字段(field)
    private string _name;
    private int _age;

    // 构造函数
    public Person(string name, int age)
    {
        _name = name;
        _age = age;
    }

    // 方法
    public void Greet()
    {
        Console.WriteLine($"Hi, I'm {_name}, {_age} years old.");
    }
}

// 用
var p = new Person("Alice", 30);
p.Greet();

属性(property):用语义代替 get/set 方法

public class Person
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("Name 不能空");
            _name = value;
        }
    }
}

var p = new Person();
p.Name = "Alice";       // 调用 setter
Console.WriteLine(p.Name);   // 调用 getter

value 是 setter 中默认的新值参数。

自动属性(最常用)

字段 + get/set 完全模板化时——一句话写完:

public class Person
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
}

编译器自动生成隐藏字段 + get/set。

只读属性

public class Circle
{
    public double Radius { get; }       // 只读
    public double Area => Math.PI * Radius * Radius;   // 表达式体

    public Circle(double r) => Radius = r;
}

{ get; } 只能在构造函数里赋值。

init-only(C# 9+)

public class Point
{
    public int X { get; init; }
    public int Y { get; init; }
}

var p = new Point { X = 1, Y = 2 };   // 对象初始化器
p.X = 99;   // ❌ 报错:init 后不能再改

init 接受对象创建期间赋值(构造函数 + 对象初始化器),之后只读。

required(C# 11+)

public class User
{
    public required string Name { get; init; }
    public required string Email { get; init; }
    public int Age { get; init; }    // 可选
}

var u = new User { Name = "A", Email = "a@x.com" };   // ✅
var u2 = new User { Name = "A" };   // ❌ 编译错误:缺 Email

required 强制使用对象初始化器时必须设置——比抛 ArgumentNull 更早发现错误。

主构造函数(C# 12+)

public class Person(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;

    public void Greet() => Console.WriteLine($"Hi {Name}");
}

var p = new Person("Alice", 30);

类声明里直接列参数——它们成为构造参数 + 类作用域内可见的"伪字段"。简化样板代码。

静态成员

public class Counter
{
    private static int _total = 0;

    public static int Total => _total;

    public Counter() { _total++; }
}

new Counter(); new Counter();
Console.WriteLine(Counter.Total);   // 2

静态成员属于,不属于任何实例。所有实例共享。

静态构造函数

public class Config
{
    public static readonly string Path;

    static Config()
    {
        Path = Environment.GetEnvironmentVariable("CONFIG_PATH") ?? "./config.json";
    }
}

第一次访问类的任何静态成员时执行一次——线程安全。

readonly 字段

public class Order
{
    public readonly DateTime CreatedAt;     // 字段只能在构造里赋值

    public Order() { CreatedAt = DateTime.UtcNow; }
}

readonly 字段 vs 只读自动属性 { get; }:行为相似,属性更主流——除非有特殊性能 / API 兼容理由。

访问修饰符

谁能访问
public 任何代码
private(默认) 本类
protected 本类 + 子类
internal 本程序集
protected internal 子类 或 本程序集
private protected(C# 7.2+) 子类 本程序集
file(C# 11+) 本文件

默认 private——除非有理由公开,否则保持。

对象初始化器

public class Address
{
    public string City { get; set; } = "";
    public string Zip { get; set; } = "";
}

var addr = new Address
{
    City = "Beijing",
    Zip = "100000",
};

// 等价于
var addr2 = new Address();
addr2.City = "Beijing";
addr2.Zip = "100000";

可以嵌套 + 初始化集合:

var person = new Person
{
    Name = "Alice",
    Addresses = { new Address { City = "X" }, new Address { City = "Y" } },
};

this

public class Box
{
    public int Width;

    public Box(int width)
    {
        this.Width = width;   // this. 区分参数和字段
    }
}

this 指当前实例——必要时显式(同名时);其他时候可省。

部分类(partial class)

// File1.cs
public partial class Form
{
    public void Init() { ... }
}

// File2.cs
public partial class Form
{
    public void Render() { ... }
}

跨文件拆同一个类。代码生成器(如 WinForms、source generators)大量用。

→ 下一篇 继承与多态