注释
此内容由 Pearson Education, Inc. 的许可从 框架设计指南:可重用 .NET 库的约定、习惯和模式(第 2 版)重新打印。 该版于2008年出版,此后该书已于 第三版全面修订。 此页上的一些信息可能已过期。
扩展方法是一种语言功能,允许使用实例方法调用语法调用静态方法。 这些方法必须至少采用一个参数,该参数表示该方法要对其运行的实例。
定义此类扩展方法的类称为“发起人”类,必须将其声明为静态类。 若要使用扩展方法,必须导入定义发起方类的命名空间。
❌ 避免轻率地定义扩展方法,尤其是在你不拥有的类型上。
如果确实拥有类型的源代码,请考虑改用常规实例方法。 如果你没有所有权,但你想添加一种方法,请务必小心。 滥用扩展方法可能使那些原本并未设计为包含这些方法的类型API变得杂乱无章。
✔️ 请考虑在以下任一方案中使用扩展方法:
为了提供与每个接口实现相关的辅助功能,条件是这些功能能够在核心接口的基础上编写。 这是因为具体实现不能直接分配给接口。 例如,
LINQ to Objects
运算符作为所有类型的 IEnumerable<T> 扩展方法实现。 因此,任何IEnumerable<>
实现都自动启用 LINQ。当实例方法会引入对某种类型的依赖,但这种依赖会破坏依赖管理规则时。 例如,从 String 到 System.Uri 的依赖可能是不需要的,因此,从依赖管理的角度来看,
String.ToUri()
实例方法返回System.Uri
将是错误的设计。 一个返回Uri.ToUri(this string str)
的静态扩展方法System.Uri
会是更好的设计。
❌ 避免在 System.Object 上定义扩展方法。
VB 用户无法使用扩展方法语法对对象引用调用此类方法。 VB 不支持调用此类方法,因为在 VB 中,将引用声明为 Object 会强制其上的所有方法调用延迟绑定(实际调用的成员在运行时确定),同时在编译时(早期绑定)确定对扩展方法的绑定。
请注意,该准则适用于存在相同绑定行为的其他语言,或者不支持扩展方法。
❌ 请勿将扩展方法放在与扩展类型的同一命名空间中,除非将方法添加到接口或依赖项管理。
❌ 避免使用同一签名定义两个或多个扩展方法,即使它们驻留在不同的命名空间中也是如此。
✔️ 如果类型是接口,并且扩展方法用于大多数或全部情况,请考虑在与扩展类型相同的命名空间中定义扩展方法。
❌ 请勿定义在通常与其他功能关联的命名空间中实现功能的扩展方法。 而是在与其所属的功能关联的命名空间中定义它们。
❌ 避免专用于扩展方法的命名空间的泛型命名(例如,“扩展”)。 请改用描述性名称(例如“路由”)。
部分内容 © 2005, 2009 Microsoft 公司。 保留所有权利。