字段与访问修饰符
本教程共 100 篇 · 第 29 篇 · 更新于 2026-07-31 · 约 8 分钟阅读
29. 字段与访问修饰符
本节目标:掌握 public/private/protected/internal 的作用范围,理解封装思想并规范字段命名。
为什么要有权限
你写的类将来可能被自己、被同事、甚至被别的项目的代码使用。如果不加任何限制,类的内部字段谁都能改、谁都能读,数据很容易被破坏:余额被改成负数、状态被悄悄篡改。
访问修饰符(access modifier)就是给类成员(字段、方法等)划的”可见范围”。选对修饰符,等于给代码装上了门禁:该暴露的留门,不该暴露的锁起来。这是面向对象”封装(encapsulation)“思想的直接体现。
四个核心修饰符
C# 里最常用的是这四个,范围从小到大:
private:只有本类内部能访问。protected:本类 + 子类能访问。internal:同一个程序集(通常是一个项目 / 一个 dll)内能访问。public:谁都能访问。
Note
protected和internal互不包含: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(如
Student、GetScore) - 私有字段:常用
_camelCase(如_price)或camelCase(如price) - 公开成员(字段/属性/方法):PascalCase
- 局部变量、参数:camelCase(如
value)
Tip命名风格团队统一即可。本教程私有字段采用
_camelCase,下划线开头便于和方法里的局部变量区分,一眼就能认出”这是字段”。
怎么选修饰符
| 你的意图 | 用哪个 |
|---|---|
| 只给自己类内部用 | private |
| 想给子类用、对外人保密 | protected |
| 同项目内部共用、不对外 | internal |
| 作为对外接口开放 | public |
Warning别图省事把所有成员都设成
public。过度暴露会让调用方随意破坏对象内部状态,封装就白做了。默认写private,需要对外才逐级放开。
常见坑
- 忘了默认是 private:在类里写了个字段以为外面能用,结果在别处访问不了——因为默认私有。
- 类默认是 internal:想让别的程序集用你的类,记得把类标
public。 - 过度公开:把本该私有的数据设成
public,等于撤掉了所有保护。 - 混淆 protected 与 internal:一个看继承关系,一个看程序集边界,不是一回事。
最佳实践
- 字段默认
private,需要对外读写的用public方法/属性包一层。 - 对外接口尽量小而稳,内部实现细节藏起来。
- 私有字段用
_camelCase,公开成员用 PascalCase,保持统一。 - 写类库时,绝大多数成员应是
internal或private,只把真正要给人用的设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 管程序集边界。封装是面向对象最重要的原则之一,而修饰符就是它的执行工具。