扩展方法必须定义在public static非泛型非嵌套类中,this参数须为首个实参且类型匹配目标类型,调用前需using命名空间,c#14起支持extension块语法但需sdk≥.net8。

扩展方法写不对,90% 是因为类没声明为 static,或者忘了 using 命名空间——不是语法太难,是编译器报错信息容易误导你往别处查。
扩展方法必须定义在 static 类里,且不能嵌套
哪怕只加一个 IsEmpty(),类也必须显式写成 public static class StringExtensions。写成 public class StringExtensions 或 public static class Utils<t></t> 都会触发编译错误,典型提示是:The first parameter of an extension method cannot be of type 'object'——这其实是编译器“猜错了”问题根源,真正原因就是类非静态或类是泛型。
- 类名随意,但建议按功能命名(如
StringExtensions、TextBoxExtensions) - 类必须是
public,否则其他程序集无法访问 - 类里所有成员都必须是静态的;混入实例字段或方法会直接编译失败
- 不支持嵌套类:不能把扩展方法写在另一个类内部(比如
class A { public static class B { ... } })
this 参数是硬性要求,不是可选修饰符
this string s 中的 this 必须出现在第一个参数前,类型必须和你要扩展的目标一致。它不是语法糖里的“隐式上下文”,而是实打实传进去的参数——"abc".IsEmpty() 等价于 StringExtensions.IsEmpty("abc")。
-
this参数不能加ref或out(this ref string s不合法) - 参数类型不能是
dynamic,也不能是指针类型(如char*) - 运行时该参数就是原始对象,所以
s?.Length安全,但s.Length在null上仍会抛NullReferenceException - 空引用可以调用扩展方法(这点和实例方法不同),但方法体里若没判空,照样崩
调用前必须 using 命名空间,IntelliSense 不会自动帮你导
即使扩展方法定义完全正确,没加 using MyExtensions;,编译器就当它不存在,报错:'string' does not contain a definition for 'WordCount'。VS 有时弹“快速修复”,但依赖它容易漏掉跨文件或跨项目场景。
- 如果扩展类在默认命名空间(无
namespace块),则无需using,但不推荐——项目大了极易冲突 - 多个扩展类可以放在同一命名空间下,一个
using就能全导入 - 若扩展方法在另一个程序集(DLL)里,除了
using,还必须添加对该程序集的引用 - 优先级规则:同名时,实例方法永远覆盖扩展方法,哪怕扩展方法在更近的命名空间里
C# 14 的 extension 块写法更简洁,但要注意兼容性
从 C# 14 开始,可以用 extension(string s) { ... } 语法替代传统 this 参数,支持在一个块里定义多个成员(方法、属性、运算符),但底层仍是静态方法,生成的 IL 完全一致。
- 写法示例:
extension(string str) { public int WordCount() => str.Split(' ').Length; } - 仍需定义在非泛型、非嵌套的
public static class中 - 目标类型(如
string)写在extension(...)括号里,不是方法签名里 - 如果你的项目还在用 .NET 6 / C# 12,这种写法会直接编译失败——得确认 SDK 版本和语言版本是否 ≥ C# 14
最容易被忽略的是 this 参数的“实参”本质:它参与 null 判定、可被重载解析、在反射中就是普通参数。很多人以为写了 this 就自动安全,结果在 null 上调用后进方法体才崩,调试时绕一大圈。










