什么时候创建扩展方法是正确的?

bra*_*mus 13 .net c# extension-methods design-guidelines

我有一段代码如下:

public class ActivityHelper
{
    public void SetDate(IList<Activity> anActivityList)
    {
        foreach(Activity current in anActivityList)
        {
            current.Date = DateTime.Now;
        }
    }
    //More methods, properties, fields, etc...
}
Run Code Online (Sandbox Code Playgroud)

这可以很容易地转换为扩展方法.例如:

public static void SetDate(this IList<Activity> aList)
{
    foreach(Activity current in anActivityList)
    {
        current.Date = DateTime.Now;
    }
}
Run Code Online (Sandbox Code Playgroud)

原始函数不使用ActivityHelper类中的任何实例特定数据或方法,这使得它看起来像是在错误的位置.这是编写扩展方法的正确时间吗?创建扩展方法的正确方案是什么?

Mar*_*ade 12

Brad Adams撰写了关于扩展方法设计指南的文章:

考虑在以下任何一种情况下使用扩展方法:

  • 如果所述功能可以根据核心接口编写,则提供与接口的每个实现相关的辅助功能.这是因为否则不能将具体实现分配给接口.例如,LINQ to Objects运算符被实现为所有IEnumerable类型的扩展方法.因此,任何IEnumerable <>实现都自动启用LINQ.

  • 当实例方法会引入某种类型的依赖关系时,这种依赖关系会破坏依赖关系管理规则.例如,从String到System.Uri的依赖可能是不可取的,因此从依赖关系管理角度来看,返回System.Uri的String.ToUri()实例方法将是错误的设计.返回System.Uri的静态扩展方法Uri.ToUri(this string str)将是一个更好的设计.


Ree*_*sey 6

我认为扩展方法仅在有令人信服的理由使该方法成为扩展方法时才适用.

如果类型是您无法控制的类型,并且该方法应该看起来是该类型的组成部分,或者如果有令人信服的理由不将该方法直接放在该类型上(例如创建不需要的依赖项),那么扩展方法可能是合适的.

就个人而言,如果您的API用户期望在处理活动集合时已经使用"ActivityHelper"类,那么我可能不会为此创建扩展方法.标准的非扩展方法实际上是一个更简单的API,因为它易于理解和发现.从使用的角度来看,扩展方法很棘手 - 你正在调用一个"看起来像"的方法,它存在于实际存在之外的某个地方.虽然这可以简化语法,但它会降低可维护性和可发现性.

  • 真可发现性.如果您不知道扩展方法存在,您将永远找不到它 - 除非您包含正确的命名空间,否则不会出现在intellisense中. (2认同)