1.3. 面向对象编程

1.3.1. 类与对象

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

    // 属性(推荐用属性替代公有字段)
    public string Name
    {
        get => _name;
        set => _name = value ?? throw new ArgumentNullException();
    }

    public int Age
    {
        get => _age;
        set => _age = value >= 0 ? value : 0;
    }

    // 自动属性(编译器自动生成字段)
    public string Email { get; set; }

    // 只读属性
    public bool IsAdult => Age >= 18;

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

    // 方法
    public virtual void Introduce()
    {
        Console.WriteLine($"Hi, I'm {Name}, {Age} years old.");
    }

    // 静态成员
    public static Person CreateDefault()
        => new Person("Guest", 0);

    public override string ToString()
        => $"Person(Name={Name}, Age={Age})";
}

// 使用
var alice = new Person("Alice", 30);
alice.Introduce();

1.3.2. record 类型(C# 9+)

不可变数据模型的首选:

// record = 值语义的引用类型
public record Person(string Name, int Age);

// 使用
var p1 = new Person("Alice", 30);
var p2 = new Person("Alice", 30);

Console.WriteLine(p1 == p2);              // true(值比较)
Console.WriteLine(p1);                     // Person { Name = Alice, Age = 30 }

var p3 = p1 with { Age = 31 };            // with 表达式(非破坏性修改)

// record struct(值类型 record)
public readonly record struct Point(int X, int Y);

小技巧

对于 DTO、配置模型、事件等不可变数据,优先使用 record。

1.3.3. 继承与多态

public class Animal
{
    public virtual void MakeSound()
        => Console.WriteLine("...");
}

public class Dog : Animal
{
    public override void MakeSound()
        => Console.WriteLine("Woof!");
}

public class Cat : Animal
{
    public override void MakeSound()
        => Console.WriteLine("Meow!");
}

// 多态
Animal[] animals = { new Dog(), new Cat() };
foreach (var animal in animals)
    animal.MakeSound();     // Woof! Meow!

1.3.4. 抽象类与接口

// 抽象类
public abstract class Shape
{
    public abstract double GetArea();
    public virtual void Draw()
        => Console.WriteLine("Drawing shape");
}

public class Circle : Shape
{
    public double Radius { get; }
    public Circle(double radius) => Radius = radius;

    public override double GetArea()
        => Math.PI * Radius * Radius;
}

// 接口(C# 8+ 支持默认实现)
public interface IComparable<T>
{
    int CompareTo(T other);  // 抽象方法
}

public interface ILogger
{
    void Log(string message);
    void LogError(string message)  // 默认实现
        => Log($"[ERROR] {message}");
}

重要

抽象类 vs 接口:

  • 抽象类:有共享状态(字段)、部分实现、"is-a" 关系

  • 接口:无状态、纯行为契约、"can-do" 关系

  • 一个类只能继承一个抽象类,但可实现多个接口

1.3.5. 委托与事件

// 委托定义
public delegate void NotifyHandler(string message);

// 事件发布者
public class Button
{
    // 事件声明
    public event EventHandler? Clicked;
    public event EventHandler<string>? TextChanged;

    public void SimulateClick()
        => Clicked?.Invoke(this, EventArgs.Empty);
}

// 事件订阅者
public class UIHandler
{
    public void Subscribe()
    {
        var btn = new Button();
        btn.Clicked += OnButtonClicked;      // 订阅
        btn.Clicked += (s, e) => Console.WriteLine("匿名处理");
    }

    private void OnButtonClicked(object? sender, EventArgs e)
        => Console.WriteLine("按钮被点击!");
}

// Func / Action 内置委托
Func<int, int, int> add = (a, b) => a + b;
Action<string> log = msg => Console.WriteLine(msg);

1.3.6. 泛型

// 泛型类
public class Repository<T> where T : class
{
    private readonly List<T> _items = new();

    public void Add(T item) => _items.Add(item);
    public T? GetById(int id) => _items.ElementAtOrDefault(id);
}

// 泛型方法
public T? Find<T>(IEnumerable<T> source, Func<T, bool> predicate)
    => source.FirstOrDefault(predicate);

// 泛型约束
public class DataStore<T> where T : struct          // 值类型约束
public class Service<T> where T : new()             // 无参构造函数约束
public class Processor<T> where T : IComparable<T>  // 接口约束