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

时间:2011-02-01 00:22:21

标签: c# .net 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...
}

这很容易转换为扩展方法。例如:

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

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

5 个答案:

答案 0 :(得分:12)

布拉德·亚当斯写过关于extension method design guidelines

的文章
  

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

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

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

  •   

答案 1 :(得分:6)

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

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

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

答案 2 :(得分:4)

根据我的经验,扩展方法在以下方面效果最佳:

  • 没有副作用(我的团队编写的大部分扩展方法都有副作用,我们最终删除了因为它们引起的问题比他们帮助的更多)。
  • 提供适用于他们所扩展类型的每个可能实例或值的功能。 (再次引用我的团队的一个例子,string.NormalizeUrl()是不合适的,因为并非所有字符串都是偶数URL)

答案 3 :(得分:0)

我通常会创建扩展方法来帮助我编写流畅的代码。它通常取决于您正在创建的方法。

如果您认为该方法应该已经在框架中并且过于笼统,那么可以为此创建扩展方法。

但是你需要首先分析你所扩展的类将始终处于你的扩展方法可以处理的状态。

对于布拉德文章的指南

http://blogs.msdn.com/b/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx

答案 4 :(得分:0)

实质上,扩展方法为Helper方法提供了更流畅的样式语法。这转化为看似为类型或接口的所有实现添加功能的能力。

但是,我通常避免使用void返回类型声明扩展方法,因为我觉得这种流畅的样式语法的有用性,它允许你编写语句,当有问题的方法没有时,它被否定什么都归还。

但是,我想让智能感知技术选择你的方法会很方便......: - )