扩展方法必须定义在public static类中,本质是带this参数的静态方法;调用前需using命名空间;泛型扩展需显式约束;不支持ref/out this参数,且不能用于dynamic类型。

扩展方法必须定义在静态类里
扩展方法本质是静态方法,只是编译器做了语法糖处理。如果你把它写在普通类里,dotnet build 会直接报错:The first parameter of an extension method cannot be of type 'object'(常见但误导的错误提示),真正原因是类没声明为 static。
正确做法:新建一个类,用 static 修饰,且该类本身不能是泛型(但方法可以):
public static class StringExtensions
{
public static bool IsEmpty(this string s) => string.IsNullOrEmpty(s);
}
- 类名任意,但建议按功能命名(如
StringExtensions、EnumerableExtensions) - 类必须是
public,否则其他程序集无法访问 - 类里所有成员都必须是静态的——哪怕你只加一个扩展方法,也不能混入实例成员
this 参数必须是第一个参数且不能为 null
扩展方法签名强制要求第一个参数带 this 修饰符,类型即你要“扩展”的类型。它不是可选参数,也不是隐式传入的上下文——它是实打实的参数,会被编译器转成普通静态调用。
比如这行调用:
"hello".IsEmpty();
实际等价于:
StringExtensions.IsEmpty("hello");
-
this string s中的s在运行时就是原始对象,可被正常判空、调用方法 - 如果方法内部用了
s.Length却没判空,"hello".IsEmpty()没问题,但((string)null).IsEmpty()会抛NullReferenceException - 不支持
this ref T或this out T——扩展方法不能修改实参引用本身
调用前必须 using 对应命名空间
扩展方法不会自动出现在 IntelliSense 里,也不会被自动导入。即使类和方法定义完全正确,如果没加 using,编译器就当它不存在,报错:'string' does not contain a definition for 'IsEmpty'。
- 确保扩展方法所在类的命名空间已通过
using引入(例如using MyUtils;) - 如果扩展方法在默认命名空间(无
namespace块),则无需using,但不推荐这种写法 - VS 有时会在错误提示下给出“using”快速修复,但别依赖它——手动检查命名空间更可靠
泛型扩展方法要注意约束和推导
给泛型类型写扩展时,类型参数推导规则和普通泛型方法一致,但容易忽略约束导致编译失败。例如想给所有实现了 IComparable 的类型加排序安全的 Max 方法:
public static T Max<t>(this IEnumerable<t> source) where T : IComparable<t>
{
return source.Aggregate((a, b) => a.CompareTo(b) > 0 ? a : b);
}</t></t></t>
-
where T : IComparable<t></t>是必须的,否则a.CompareTo(b)编译不过 - 调用时
new[] { 1, 2, 3 }.Max()能正确推导出T=int;但new object[].Max()会因约束不满足而报错 - 不能对
dynamic类型使用泛型扩展方法——类型推导失败,且运行时也不支持











