【问题标题】:What is so great about extension methods? [duplicate]扩展方法有什么了不起的? [复制]
【发布时间】:2009-11-18 22:26:54
【问题描述】:

可能重复:
What Advantages of Extension Methods have you found?

好吧,首先,我意识到这听起来有争议,但我并不是要对抗。我出于真正的好奇心提出了一个严肃的问题(或者也许 puzzlement 是一个更好的词)。

为什么将扩展方法引入 .NET?除了让事情看起来不错(我所说的“不错”是指“看似实例方法”)之外,它们还有什么好处?

对我来说,任何使用这样的扩展方法的代码:

Thing initial = GetThing();
Thing manipulated = initial.SomeExtensionMethod();

具有误导性,因为它暗示 SomeExtensionMethodThing 的实例成员,这会误导开发人员相信(至少作为一种直觉......你可能会否认,但我确实观察到了这一点) (1) SomeExtensionMethod 可能被有效地实现,并且 (2) 因为 SomeExtensionMethod 实际上看起来它是 Thing 类的part,如果 Thing 修改为未来某个时间点(只要Thing 的作者知道他/她在做什么)。

但事实是扩展方法无法访问受保护的成员或它们扩展的类的任何内部工作,因此它们与任何其他静态方法一样容易损坏。

我们都知道上面的很容易是:

Thing initial = GetThing();
Thing manipulated = SomeNonExtensionMethod(initial);

来说,这似乎更多,因为没有更好的词,诚实

我错过了什么?为什么存在扩展方法?

【问题讨论】:

  • @Zarembisty:谢谢,我在发布此内容之前诚实地搜索了一个副本,但不知何故没有找到那个。如果人们想关闭它,这是可以理解的。
  • 我发现 SO 搜索只是马马虎虎;谷歌总能找到答案(谢天谢地,越来越多的答案指向 SO)

标签: c# .net extension-methods static-methods


【解决方案1】:

需要扩展方法以使 Linq 以干净的方式工作,并使用方法链接。如果必须使用“长”形式,则会导致函数调用和参数彼此分离,从而使代码难以阅读。比较:

IEnumerable<int> r = list.Where(x => x > 10).Take(5)

// What does the 5 do here?
IEnumerable<int> r = Enumerable.Take(Enumerable.Where(list, x => x > 10), 5);

就像任何东西一样,它们可能会被滥用,但是如果使用得当,扩展方法真的很有用。

【讨论】:

  • 我知道这个问题已经结束,但这是我最喜欢的答案。
  • 除了链接之外,我还想添加一件事来帮助我们扩展类的行为,而无需实际更改类。因此它有助于我们使用“开放封闭原则” - 一个类应该对扩展开放但对修改关闭。
【解决方案2】:

我认为主要的好处是可发现性。输入initial 和一个点,你就可以用它做所有的事情了。在其他地方的某个类中找到隐藏的静态方法要困难得多。

【讨论】:

  • 这难道不是 Visual Studio 功能的结果,而不是作为 C#/.NET 一部分的扩展方法的固有优势吗?
  • @Dan:是的,如果您使用另一个没有发现扩展方法并像 Intellisense 那样显示它们的编辑器,那么这个好处就没有了。
【解决方案3】:

首先,在Thing manipulated = SomeNonExtensionMethod(initial); 案例中,SomeNonExtensionMethod 与Thing manipulated = initial.SomeExtensionMethod(); 案例中的假设完全相同。事情可以改变, SomeExtensionMethod 可以打破。这就是我们程序员的生活。

其次,当我看到Thing manipulated = initial.SomeExtensionMethod(); 时,它并没有告诉我 SomeExtensionMethod() 的具体实现位置。 Thing 可以从 TheThing 继承它,而 TheThing 从 TheOriginalThing 继承它。因此,“误导”论点毫无结果。我敢打赌 IDE 会负责引导您找到正确的来源,不是吗?

有什么了不起的?它使代码更加一致。如果它适用于字符串,则看起来它是否是字符串的成员。在另一个类中有几个MyThing.doThis() 方法和几个static ThingUtil.doSomethingElse(Mything thing) 方法是很难看的。

【讨论】:

  • 对于您的第一点:我的观点是这两者实际上是相同的,但 SomeNonExtensionMethod 版本的误导性较小,因为它不会诱使您认为该方法实际上是类定义。
  • 第二点:至少如果你调用一个实例成员,你知道它是由类内部实现的,这意味着至少它可以访问受保护的成员并且应该 保证在课程更新时继续工作。
  • 最后一点:说让静态方法对对象起作用是“丑陋的”,这让我觉得非常主观。我很难看到好处。我可能希望 C# 设计团队允许用方括号替换花括号,因为这对我来说看起来更漂亮;这并不意味着他们这样做会改善语言。
  • Dan:首先:我认为它是否是类定义的一部分并不重要。要么按预期工作,要么不按预期工作。
  • Dan:第二:作为一个局外人,我对受保护成员一无所知。我不在乎 SomeExtensionMethod() 是怎么做的。太多的知识会导致假设,可能会导致隐藏的依赖关系。每当类更新时工作:我猜你对非常稳定的类使用扩展方法,比如字符串。您不会将其用于您自己的课程,因为您可以随时更改 它们
【解决方案4】:

所以你可以扩展别人的课程。不是你的……这就是优势。 (你可以说......哦,我希望他们实现这个/那个......你自己做......)

【讨论】:

  • 见鬼 - @Zarembisty 说的太对了 - 像他发布的那样去做。你得到了一切! stackoverflow.com/questions/487904/… – 扎伦比斯蒂。
  • 我的意思是,它们并没有比简单地使用静态方法给你更多的权力。
【解决方案5】:

它们非常适合基于类继承的接口自动混合功能,而无需该类显式地重新实现它。

Linq 大量使用了这一点。

用额外的功能装饰类的好方法。应用于接口而不是特定类时最有效。仍然是扩展框架类的好方法。

【讨论】:

    【解决方案6】:

    它只是一种方便的语法糖,因此您可以使用相同的语法调用方法,而不管它是否实际上是类的一部分。如果甲方发布了一个库,而乙方发布了使用该库的东西,那么使用 class.method(args) 调用所有内容比记住使用 method(class, args) 与 class.method 调用的内容更容易(参数)。

    【讨论】:

      猜你喜欢
      • 2016-12-24
      • 1970-01-01
      • 2019-10-23
      • 2019-02-15
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      相关资源
      最近更新 更多