private成员仅限于定义它的类内部直接访问,编译器强制执行该边界,静态方法可通过实例引用访问私有字段,嵌套类需显式声明访问修饰符,private保护的是位置而非身份。

private 成员只能在定义它的类内部被直接访问
这句不是语法规定,而是编译器强制执行的边界。只要代码出现在 class 大括号内、且不在嵌套类型中,就能读写 private 字段或调用 private 方法;一旦跨出这个范围——哪怕只是同文件另一个类、同一命名空间下的兄弟类、甚至继承链上的子类——编译器立刻报错,例如:CS0122: 'Person._name' is inaccessible due to its protection level。
常见错误现象包括:
- 子类里直接写
this._name = "xxx",编译失败 - 同一程序集里另一个类试图通过对象实例访问
person._name,报 CS0122 - 用反射绕过检查(
FieldInfo.SetValue())能成功,但这属于运行时行为,不改变private的编译期语义
private 不阻止类内部所有上下文的访问,但会限制作用域粒度
private 保护的是“位置”,不是“身份”。它不关心你是构造函数、实例方法、静态方法、getter/setter 还是局部函数——只要在同一个 class 定义块里,就默认拥有完全访问权。
这意味着:
- 静态方法可以读写实例的
private字段(通过传入的实例引用) - 嵌套类(
class Inner)默认不是外部类的一部分,它的成员不是private的“内部”,需显式声明为private或使用private protected - 属性的
get/set块各自独立受控:可写private set+ public get,但不能反过来用private get+ public set(C# 不允许)
和 protected / internal / private protected 混用时容易误判访问权限
尤其在有继承+多程序集场景下,private 和 private protected 表面相似,实际约束完全不同:
-
private:仅限本类,子类也不行,跨程序集更不行 -
private protected:本类 + 同一程序集内的子类(注意:不同程序集的子类仍不可访问) -
protected internal:同一程序集内任意类 + 其他程序集的子类(二者取并集)
典型坑点:把基类字段设为 private,然后在派生类里想复用逻辑,结果只能重写整套逻辑或暴露为 protected——但后者可能破坏封装。这时候该考虑的是重构,而不是降级访问修饰符。
private 的真正价值不在“防人”,而在“防自己”
它强迫你面对一个事实:类的内部状态变更必须经过明确定义的路径。比如 _balance 是 private,那所有修改都得走 Deposit() 或 Withdraw() 方法——这些方法可以校验金额、触发事件、更新时间戳。没有 private,你永远不知道哪行代码悄悄绕过了业务规则。
所以别把它当成锁,而要看作契约的起点。一旦某个字段被标记为 private,后续所有对外暴露的接口(public 属性、方法参数、事件)都得围绕它重新设计,而不是反过来迁就外部调用便利性。










