0Pricing
C# Academy · 课时

封装与不变量

隐藏内部状态,公开安全的操作,并确保类不变量始终成立(例如余额非负、数值处于有效范围内)。

封装与不变量 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 3 节课。

封装概览

目标:保护对象的状态。

  • 封装:隐藏 fields,公开安全的 APIs
  • 不变量:始终为真的规则
  • 在构造函数、setter 和方法中进行验证

只读接口

将 fields 保持为私有。向调用方提供只读属性和安全的操作。

using System;

// Expose read-only view; mutate via methods only
public class Counter
{
  private int _value;          // hidden state
  public int Value             // read-only to callers
  {
    get { return _value; }
    private set { _value = value; } // keep setter private
  }

  public void Increment()
  {
    Value = Value + 1;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Counter c = new Counter();
    c.Increment();
    c.Increment();
    Console.WriteLine("Value = " + c.Value);
  }
}

构造函数保护

构造函数设置必需的状态。防止无效输入,使对象从一开始就保持有效。

using System;

// Enforce rules early (constructor guard)
public class User
{
  public string Name { get; private set; }
  public int Age { get; private set; }

  public User(string name, int age)
  {
    if (string.IsNullOrEmpty(name)) throw new ArgumentException("name");
    if (age < 0) throw new ArgumentOutOfRangeException("age");
    Name = name;
    Age = age;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    try
    {
      User u = new User("Ada", 28);
      Console.WriteLine(u.Name + " (" + u.Age + ")");
    }
    catch (Exception ex)
    {
      Console.WriteLine("Error: " + ex.Message);
    }
  }
}

实际应用中的不变量

定义一个不变量(例如,余额 ≥ 0),并在 setter 和方法中强制执行。

using System;

// Invariant: Balance >= 0 at all times
public class BankAccount
{
  private decimal _balance;

  public decimal Balance
  {
    get { return _balance; }
    private set
    {
      if (value < 0) throw new InvalidOperationException("Balance would be negative");
      _balance = value;
    }
  }

  public BankAccount(decimal opening)
  {
    if (opening < 0) throw new ArgumentOutOfRangeException("opening");
    _balance = opening;
  }

  public void Deposit(decimal amount)
  {
    if (amount <= 0) throw new ArgumentOutOfRangeException("amount");
    Balance = Balance + amount;
  }

  public bool TryWithdraw(decimal amount)
  {
    if (amount <= 0) return false;
    if (Balance - amount < 0) return false;
    Balance = Balance - amount;
    return true;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    BankAccount a = new BankAccount(50m);
    a.Deposit(20m);
    bool ok = a.TryWithdraw(100m); // fails, invariant protected
    Console.WriteLine("ok=" + ok + " balance=" + a.Balance);
  }
}

保护集合

不要直接公开内部列表或数组。返回副本(或只读视图)以保护不变量。

using System;
using System.Collections.Generic;

public class Tags
{
  private readonly List<string> _items = new List<string>();

  public void Add(string tag)
  {
    if (string.IsNullOrWhiteSpace(tag)) return;
    _items.Add(tag.Trim());
  }

  // Expose a copy so callers cannot mutate internal list
  public List<string> GetAllCopy()
  {
    return new List<string>(_items);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Tags t = new Tags();
    t.Add(" apple ");
    t.Add("banana");
    List<string> view = t.GetAllCopy();
    view.Add("hacker"); // modifies the copy only
    Console.WriteLine("copy count=" + view.Count);
    Console.WriteLine("original count=" + t.GetAllCopy().Count);
  }
}

封装提示

检查清单:

  • 私有 fields;公共 properties/方法。
  • 在构造函数/setter 中进行验证。
  • 每次调用后都保持不变量为真。
  • 不要泄露内部集合。

封装原则

快速检查:哪种选择最能维护封装和类不变量?

回顾

回顾:使用私有 fields 和经过验证的 APIs 进行封装。定义一个不变量,并在构造函数、setter 和方法中强制执行。绝不要泄露内部集合。

常见问题解答

「封装与不变量」课时是免费的吗?

是的 — 「封装与不变量」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 3 节课。

「封装与不变量」这节课中我会学到什么?

隐藏内部状态,公开安全的操作,并确保类不变量始终成立(例如余额非负、数值处于有效范围内)。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 3 节。

「封装与不变量」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 字段、自动属性与对象初始化器
  2. 构造函数与静态成员
  3. 封装与不变量
← 返回 C# Academy