CLSCompliant(true) 是程序集级的跨语言兼容性检查机制,仅在[assembly: CLSCompliant(true)]声明后启用,强制公开API符合CLS规范,否则编译报错;它不检查私有/内部成员,也不影响运行时行为。

CLSCompliant(true) 是编译器的“跨语言质检员”
它不改变运行时行为,也不生成额外代码,而是让 C# 编译器在编译期主动检查:所有公开(public 或 protected)的类型、方法、属性、字段等,是否符合 公共语言规范(CLS)。一旦发现不兼容项(比如公开了 uint、ulong、无符号类型、带下划线开头的标识符、重载仅靠大小写区分的方法),编译器立刻报 CS3001、CS3002、CS3003 等警告(默认为错误,可降级为警告)。
必须加在程序集级别才真正生效
很多人误以为在类或方法上加 [CLSCompliant(true)] 就能“局部合规”,其实不行——CLS 合规性是程序集级别的契约。只有在 AssemblyInfo.cs(或任意 .cs 文件顶部)加上这行,才启动全局检查:
[assembly: CLSCompliant(true)]
而类型/成员上的 [CLSCompliant(true/false)] 仅用于覆盖(override)程序集默认策略,例如:
- 整个程序集设为
true,但某个内部工具类用到了UInt64→ 给该类加[CLSCompliant(false)]并加注释说明原因 - 程序集默认
false,但你想确保某几个公开 API 一定兼容 → 单独给它们标[CLSCompliant(true)]
常见踩坑:你以为兼容,其实不兼容
以下看似无害的写法,在 [assembly: CLSCompliant(true)] 下会直接编译失败:
- 公开返回
uint:public uint GetId() { ... }→ 改用int或long - 公开含下划线的名称:
public void Do_Something() { ... }→ 改为DoSomething - 两个方法仅靠首字母大小写区分:
ToString()和toString()→ CLR 视为同一签名,VB.NET 不支持,直接报错 - 泛型类型参数名含数字开头:
class Data1<t></t>→ 虽然 C# 允许,但 CLS 要求标识符以字母或下划线开头(且下划线开头本身也不推荐)
要不要开?取决于你的库是否要被其他 .NET 语言调用
如果你的程序集只供 C# 项目引用,关掉也无妨;但只要它可能被 VB.NET、F# 或 PowerShell 调用,或者作为 NuGet 包发布给公众,就必须开启。尤其注意:.NET Standard / .NET 5+ 项目默认不启用,需手动添加。另外,[CLSCompliant(true)] 对私有成员、内部成员(internal)完全不检查——所以别指望它帮你发现封装问题,它只管“对外承诺”的那一部分。










