C# 3.0 扩展方法及其在软件工程中的意义(或者它真的是一个好主意?)

C# 3.0 扩展方法及其在软件工程中的意义(或者它真的是一个好主意?),c#-3.0,extension-methods,C# 3.0,Extension Methods,对,所以李女士介绍。基本上,它允许您向现有类添加新方法,而无需从现有类中生成子类或更改其实现。我的脑海里立刻响起了警钟 1) 开始为库或标准库类实现自己的扩展方法。现在它不再标准化了 2) 在OOP中,可以通过继承或组合定义新类型。那么扩展方法究竟是什么呢?同样,在使用扩展方法时,没有定义明确的关系 3) 扩展方法是否可在项目之间移植?如果一个方法存在两个扩展方法怎么办 那么,扩展方法是值得避免的一大堆蠕虫吗?我可以看出它有优点,就像你少打字一样,但不知何故,它看起来会导致不好的练习 意见?扩展

对,所以李女士介绍。基本上,它允许您向现有类添加新方法,而无需从现有类中生成子类或更改其实现。我的脑海里立刻响起了警钟

1) 开始为库或标准库类实现自己的扩展方法。现在它不再标准化了

2) 在OOP中,可以通过继承或组合定义新类型。那么扩展方法究竟是什么呢?同样,在使用扩展方法时,没有定义明确的关系

3) 扩展方法是否可在项目之间移植?如果一个方法存在两个扩展方法怎么办

那么,扩展方法是值得避免的一大堆蠕虫吗?我可以看出它有优点,就像你少打字一样,但不知何故,它看起来会导致不好的练习


意见?

扩展方法不会添加到类型中。它们只是语法上的糖。你不能访问私人物品。扩展方法与任何使用类型的静态方法一样

他们能做的最糟糕的事情就是损害可读性和误导人们。除了语法之外,它们是不存在的

更新(重新评论): 这正是我在“误导人们”和“损害可读性”中的意思。幸运的是,VisualStudio在区分扩展方法(使用IntelliSense列表中的图标和工具提示)方面非常有用。就我个人而言,我有点倾向于在框架的任意类中添加一堆扩展方法(除了
密封的
类,在这些类中扩展方法非常有意义),除非它们为特定项目提供了显著的好处。我更喜欢在继承层次结构的顶层保留主要用于接口和类的扩展方法。这将使开发人员只在适用于框架中许多情况的情况下使用它们,而不是将任何实用方法作为扩展(在我看来,这是在整个命名空间中自动发现扩展方法的直接产物。我真希望C#要求您在特定的
上使用
指令添加一个
,而不是自动导入
命名空间
中的所有扩展)

根据我的经验,如果你不过度使用扩展方法,将每一个使用过几次的实用方法(我见过一些人这样做)都作为一个扩展,这很少是一个维护问题。如果使用得当,它将提高可读性

将类与扩展方法混在一起不是一件好事。在极端情况下,这可能是危险的。通过向类中添加与现有扩展同名的方法,可能会引入名称冲突问题。这可能会破坏以前调用扩展的代码段,现在正在调用新的me方法。

在我看来,这是与扩展方法相关的最大问题。这使得良好的扩展命名非常重要。

不,这不是一个值得避免的蠕虫。它可以使生活简单得多,而且在我看来,它允许您将类型的核心操作与“helper”分开方法,这些方法只能从那些核心操作中实现。我一直试图以这种方式使用扩展方法,即使它们不是真正必要的(例如,我有一个基类来放置它们,我控制着代码)

您需要了解,当导入包含扩展方法的适当命名空间时,扩展方法只是使静态方法调用看起来像实例方法的一种方法。特别是:

  • 它不会向类型中添加方法,因此不会使标准库成为“非标准”库。它只是意味着,如果您有可用的扩展方法,您可能可以更轻松地使用这些库
  • 有一个与扩展方法定义的显式关系:扩展方法声明它正在“扩展”的类型第一个参数的类型。这不是组合或聚合,但我不明白为什么这是一个问题。如果某个参数有用并且实际上不会使设计变得更糟,那么它是否是传统OO的一部分重要吗
  • 是的,扩展方法在项目之间是可移植的。与往常一样,如果两个同名的扩展方法同时可见,则会有一些规则
接口上的扩展方法非常好,允许简单的方法链接等。我更愿意看到扩展方法调用,而不是Java中的显式静态调用:

// Explicit helper method call
Collections.sort(collection);
// With extensions, this could be:
collection.sort();
但也有一些缺点:

  • 它不允许派生类型以更有效的方式重写实现。当然,派生类型可以声明具有相同签名的方法,但只有在编译时类型合适时才会使用
  • 扩展方法在C#中被发现的方式是一种痛苦。我在其他地方已经说过了
  • 使用动态类型时,扩展方法不可用

总的来说,我认为它们很可爱——如果使用得当,它们会产生很大的不同。如果没有它们,我当然不想使用LINQ。

扩展方法根本不会修改现有的类,它们只是“语法糖”或者是一个将静态方法附加到类的编译器技巧。只需在另一个类中创建一个普通的静态实用程序方法,将所需的类作为该方法的第一个参数,就可以达到相同的目的。我明白你关于“添加”的观点方法,从而取消类的标准化,但实际情况并非如此。实际上,我发现扩展方法对于向现有类中添加特定于域的方法或实用工具方法非常直观和方便,否则这些方法将无法修改。

您可以关闭警铃。扩展方法只会产生很小的影响不同于
SomeClass.SomeStaticMethod(someVar, someArg);
someVar.SomeStaticMethod(someArg);
trimmed = string.Trim(str);
public static void DisposeIfNotNull(this IDisposable d)
{
    if (d != null)
        d.Dispose();
}