首页 / C# 入门教程 / 字段与访问修饰符

C# 入门教程

字段与访问修饰符

本教程共 100 篇 · 第 29 篇 · 更新于 2026-07-31 · 约 8 分钟阅读

C#C# 入门教程编程语言字段访问修饰符封装

29. 字段与访问修饰符

本节目标:掌握 public/private/protected/internal 的作用范围,理解封装思想并规范字段命名。

为什么要有权限

你写的类将来可能被自己、被同事、甚至被别的项目的代码使用。如果不加任何限制,类的内部字段谁都能改、谁都能读,数据很容易被破坏:余额被改成负数、状态被悄悄篡改。

访问修饰符(access modifier)就是给类成员(字段、方法等)划的”可见范围”。选对修饰符,等于给代码装上了门禁:该暴露的留门,不该暴露的锁起来。这是面向对象”封装(encapsulation)“思想的直接体现。

四个核心修饰符

C# 里最常用的是这四个,范围从小到大:

  • private:只有本类内部能访问。
  • protected:本类 + 子类能访问。
  • internal:同一个程序集(通常是一个项目 / 一个 dll)内能访问。
  • public:谁都能访问。
Note

protectedinternal 互不包含:protected 看”是不是子孙”,internal 看”是不是同程序集”。两者没有谁大谁小,是两条不同的维度。

private:只藏在类内部

private 成员只能在本类里用,外面碰不到。它是封装的基础——把核心数据锁起来,只通过你允许的方式去动它。

namespace CSharpDemo;

BankAccount acc = new();
acc.Deposit(100m);
Console.WriteLine(acc.GetBalance());  // 100

class BankAccount
{
    private decimal balance;   // 余额,外部不能直接改

    public void Deposit(decimal amount) => balance += amount;
    public decimal GetBalance() => balance;
}
Note

不写任何修饰符时,类成员默认就是 private。“默认私有”是 C# 的一项安全约定——漏写反而更保守、更安全。

public:对外敞开

public 成员对所有代码开放,通常用来暴露类的”对外接口”:别人用你的类,靠的就是这些 public 成员。

namespace CSharpDemo;

Person p = new();
p.Name = "小明";
Console.WriteLine(p.Name);

class Person
{
    public string Name = "";   // 任何地方都能读和改
}

protected:留给孩子用

protected 成员在本类及其派生类(子类)里可见。它适合”父类想给子类用、但不想让外人碰”的场景。继承章节会细讲,先看个直观例子:

namespace CSharpDemo;

Dog dog = new();
dog.Show();   // 能访问父类的 Species

class Animal
{
    protected string Species = "";   // 子类也能用
}

class Dog : Animal
{
    public void Show()
    {
        Species = "犬科";
        Console.WriteLine(Species);
    }
}
Tip

把”只允许子类用”的成员设 protected,既挡住了外部乱改,又给将来扩展留口子。封装不是一味锁死,而是”该收收、该放放”。

internal:同程序集内可见

internal 成员只在当前程序集(通常一个项目 / 一个 dll)可见。当你写一个类库,往往只想把少数几个 public 接口暴露给使用者,大量内部辅助方法标成 internal,对外完全隐形。

Note

类自身的默认访问级别是 internal;类成员的默认访问级别是 private。两个默认值别搞混:新建一个类,没写修饰符,它在别的程序集里是看不见的。

组合修饰符

除了单独使用,还有两个组合:

  • protected internal:子类 同程序集,二者满足其一即可。
  • private protected:既是子类 同程序集,两者都要满足。

初学阶段先掌握前四个,这两个组合用到再查即可。

封装:把字段藏起来

好的做法是用 private 字段存数据,再用 public 的方法(或后续的”属性”)来控制读写,并在其中加校验,避免被乱改。

namespace CSharpDemo;

Student s = new();
s.SetScore(120);   // 被挡掉,score 没变
s.SetScore(88);
Console.WriteLine(s.GetScore());  // 88

class Student
{
    private int score;   // 私有字段

    public void SetScore(int value)
    {
        if (value < 0 || value > 100)
            return;      // 简单校验,挡住非法值
        score = value;
    }

    public int GetScore() => score;
}
Note

直接 public int Score 谁都能写成 999。封装后加一道校验,数据才可靠。后续的”属性(property)“会让这种”带校验的读写”写得更优雅,一行就能带逻辑。

命名约定

namespace CSharpDemo;

class Product
{
    private decimal _price;   // 私有字段,下划线开头是常见风格
    public string Name = "";
}
  • 类名、方法名:PascalCase(如 StudentGetScore
  • 私有字段:常用 _camelCase(如 _price)或 camelCase(如 price
  • 公开成员(字段/属性/方法):PascalCase
  • 局部变量、参数:camelCase(如 value
Tip

命名风格团队统一即可。本教程私有字段采用 _camelCase,下划线开头便于和方法里的局部变量区分,一眼就能认出”这是字段”。

怎么选修饰符

你的意图用哪个
只给自己类内部用private
想给子类用、对外人保密protected
同项目内部共用、不对外internal
作为对外接口开放public
Warning

别图省事把所有成员都设成 public。过度暴露会让调用方随意破坏对象内部状态,封装就白做了。默认写 private,需要对外才逐级放开。

常见坑

  1. 忘了默认是 private:在类里写了个字段以为外面能用,结果在别处访问不了——因为默认私有。
  2. 类默认是 internal:想让别的程序集用你的类,记得把类标 public
  3. 过度公开:把本该私有的数据设成 public,等于撤掉了所有保护。
  4. 混淆 protected 与 internal:一个看继承关系,一个看程序集边界,不是一回事。

最佳实践

  • 字段默认 private,需要对外读写的用 public 方法/属性包一层。
  • 对外接口尽量小而稳,内部实现细节藏起来。
  • 私有字段用 _camelCase,公开成员用 PascalCase,保持统一。
  • 写类库时,绝大多数成员应是 internalprivate,只把真正要给人用的设 public

internal 在类库里怎么用

假设你写一个算账的类库,内部有个 RoundMoney 辅助方法,外部用户根本不该碰。把它标 internal,编译出的 dll 外就看不见它,用户只能调用你公开的 public 接口。这样既隐藏实现细节,又不污染对外 API。

namespace CSharpDemo;

class TaxCalculator
{
    public decimal Calculate(decimal price) => price + InternalFee();
    internal decimal InternalFee() => 0.5m;   // 仅本程序集可见
}
Note

如果这个类库被别的项目引用,InternalFee 对外不可见,调用方连名字都看不到,避免被误用。

封装不是越严越好

强调封装,不等于把所有东西都锁成 private。对外该给的接口要大方给 public,否则别人没法用你的类。封装的尺度是:数据(字段)尽量私有,操作(方法/属性)按需公开,内部实现细节藏起来。

Tip

一个实用的判断:这个成员是”对外契约”还是”内部零件”?契约用 public,零件用 private/internal。拿不准时,先 private,需要用再放开,比一上来全 public 安全。

修饰符与可测试性

写单元测试时,常需要测类的内部逻辑。如果什么都 private,测试只能绕远路。这时可以用 internal 配合 InternalsVisibleTo(让测试项目能看到内部成员),既保住了对普通调用方的隐藏,又方便测试。这是 internal 一个很实用的进阶用法。

一个常见误区

有初学者以为 private 的成员”完全无法被外部读到”。其实封装的目的不是”读不到”,而是”通过我允许的方式读、改时受到控制”。用属性(property)暴露只读访问,既安全又方便——这是后续章节的重点。

小结

访问修饰符把”该暴露的暴露、该藏的藏起来”。private 保安全,public 给接口,protected 留给子类,internal 管程序集边界。封装是面向对象最重要的原则之一,而修饰符就是它的执行工具。