扩展方法Extension Methods

扩展方法是一种语言特性,允许使用实例方法调用语法来调用静态方法。Extension methods are a language feature that allows static methods to be called using instance method call syntax. 这些方法必须至少使用一个参数,该参数表示方法要操作的实例。These methods must take at least one parameter, which represents the instance the method is to operate on.

定义此类扩展方法的类称“sponsor”类,必须将其声明为静态。The class that defines such extension methods is referred to as the "sponsor" class, and it must be declared as static. 要使用扩展方法,必须导入定义 sponsor 类的命名空间。To use extension methods, one must import the namespace defining the sponsor class.

X 避免 轻率定义扩展方法,尤其是在你不拥有的类型上。X AVOID frivolously defining extension methods, especially on types you don’t own.

如果拥有某一类型的源代码,请考虑使用常规实例方法。If you do own source code of a type, consider using regular instance methods instead. 如果没有,并且想要添加方法,请务必小心。If you don’t own, and you want to add a method, be very careful. 随意使用扩展方法可能会使本来不具备这些方法的类型产生混乱的API。Liberal use of extension methods has the potential of cluttering APIs of types that were not designed to have these methods.

✓ 考虑在以下任何一种情况下使用扩展方法:✓ CONSIDER using extension methods in any of the following scenarios:

  • 提供与接口的每个实现相关的辅助功能(如果上述功能可以根据核心接口编写)。To provide helper functionality relevant to every implementation of an interface, if said functionality can be written in terms of the core interface. 这是因为不能将具体实现分配给接口。This is because concrete implementations cannot otherwise be assigned to interfaces. 例如,LINQ to Objects 运算符作为所有 IEnumerable<T> 类型的扩展方法被实现。For example, the LINQ to Objects operators are implemented as extension methods for all IEnumerable<T> types. 因此,任何 IEnumerable<> 实现都会自动启用LINQ。Thus, any IEnumerable<> implementation is automatically LINQ-enabled.

  • 当实例方法在某种类型上引入依赖关系,但这样的依赖关系会破坏依赖关系管理规则的时候。When an instance method would introduce a dependency on some type, but such a dependency would break dependency management rules. 例如,从 StringSystem.Uri 的依赖关系可能是不可取的,因此返回 System.UriString.ToUri() 实例方法从依赖关系管理的角度来看可能存在设计错误。For example, a dependency from String to System.Uri is probably not desirable, and so String.ToUri() instance method returning System.Uri would be the wrong design from a dependency management perspective. 返回 System.Uri 的静态扩展方法 Uri.ToUri(this string str) 可能是更好的设计。A static extension method Uri.ToUri(this string str) returning System.Uri would be a much better design.

X 避免System.Object 上定义扩展方法。X AVOID defining extension methods on System.Object.

VB 用户将无法使用扩展方法语法在对象引用上调用此类方法。VB users will not be able to call such methods on object references using the extension method syntax. VB 不支持调用这样的方法,因为在 VB 中,将引用声明为 Object 会强制对方法的所有方法调用进行延迟绑定(在运行时确定调用的实际成员),而在编译时确定对扩展方法的绑定(早期绑定)。VB does not support calling such methods because, in VB, declaring a reference as Object forces all method invocations on it to be late bound (actual member called is determined at runtime), while bindings to extension methods are determined at compile-time (early bound).

请注意,该准则适用于存在相同绑定行为的其他语言,或者不支持扩展方法的其他语言。Note that the guideline applies to other languages where the same binding behavior is present, or where extension methods are not supported.

X 切忌将扩展方法放在与扩展类型相同的命名空间中,除非它用于向接口添加方法或用于依赖关系管理。X DO NOT put extension methods in the same namespace as the extended type unless it is for adding methods to interfaces or for dependency management.

X 避免定义两个或多个具有相同签名的扩展方法,即使它们位于不同的命空间中。X AVOID defining two or more extension methods with the same signature, even if they reside in different namespaces.

✓ 考虑在与扩展类型相同的命名空间中定义扩展方法,前提是该类型是接口并且打算在大多数或所有情况下使用该扩展方法。✓ CONSIDER defining extension methods in the same namespace as the extended type if the type is an interface and if the extension methods are meant to be used in most or all cases.

X 请勿定义在通常与其他功能相关联的命名空间中实现功能的扩展方法。X DO NOT define extension methods implementing a feature in namespaces normally associated with other features. 而是在与它们所属的功能相关联的命名空间中定义它们。Instead, define them in the namespace associated with the feature they belong to.

X 避免对专用于扩展方法的命名空间进行通用命名(例如,“扩展”)。X AVOID generic naming of namespaces dedicated to extension methods (e.g., "Extensions"). 而是使用描述性名称(例如,“路由”)。Use a descriptive name (e.g., "Routing") instead.

部分版权 © 2005, 2009 Microsoft Corporation。保留所有权利。Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

经 Pearson Education, Inc 授权,转载自框架设计准则:可重用的 .NET 库的约定、习惯用语和模式,第 2 版 作者:Krzysztof Cwalina 和 Brad Abrams,由 Addison Wesley Professional 于 2008 年 10 月 22 日印发,作为 Microsoft Windows 开发系列的一部分。Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by Addison-Wesley Professional as part of the Microsoft Windows Development Series.

请参阅See also