14

我有一段代码如下:

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 类中的任何实例特定数据或方法,这使得它看起来像是在不正确的位置。这是编写扩展方法的正确时间吗?创建扩展方法的正确场景是什么?

4

5 回答 5

12

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

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

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

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

于 2011-02-01T00:26:07.587 回答
6

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

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

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

于 2011-02-01T00:27:34.713 回答
4

根据我的经验,扩展方法在以下情况下效果最好:

  • 没有副作用(我的团队编写的大多数扩展方法都有副作用,我们最终删除了,因为它们造成的问题多于帮助的问题)
  • 提供适用于它们扩展的类型的每个可能实例或值的功能。(再次引用我团队的一个例子,这string.NormalizeUrl()是不合适的,因为并非所有字符串都是 URL)
于 2011-02-01T00:30:10.420 回答
0

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

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

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

有关布拉德文章的指南

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

于 2011-02-01T00:28:58.940 回答
0

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

但是,我通常会避免使用返回类型声明扩展方法void,因为我觉得当相关方法不返回任何内容时,这种流畅的样式语法的有用性会被否定,它允许您编写语句。

但是,我想让 IntelliSense 拾取您的方法会很方便...... :-)

于 2011-02-01T00:45:07.917 回答