C#的"非信徒"问我扩展方法的目的是什么.我解释说,然后您可以向已定义的对象添加新方法,尤其是当您不拥有/控制原始对象的源时.
他提出"为什么不在自己的课堂上添加一种方法?" 我们一直在四处走动(以一种很好的方式).我的一般回答是,它是工具带中的另一个工具,他的回答是它是一种无用的工具浪费......但我认为我会得到一个更"开明"的答案.
有哪些场景你使用了你不能(或不应该)使用的方法添加到你自己的类上的扩展方法?
扩展方法的唯一优点是代码可读性.而已.
扩展方法允许您这样做:
foo.bar();
而不是这个:
Util.bar(foo);
现在C#中有很多东西都是这样的.换句话说,C#中有许多功能似乎微不足道,并且本身并没有很大的好处.然而,一旦开始将这些功能组合在一起,您就会开始看到比其各部分总和更大的东西.LINQ从扩展方法中获益很大,因为如果没有它们,LINQ查询几乎是不可读的.LINQ可以在没有扩展方法的情况下实现,但不实用.
扩展方法很像C#的部分类.他们自己并不是很有帮助,而且似乎微不足道.但是当你开始使用需要生成代码的类时,部分类开始变得更有意义.
不要忘记工具!当你在Foo类型上添加扩展方法M时,你会在Foo的intellisense列表中得到'M'(假设扩展类在范围内).这使得'M'比MyClass.M(Foo,...)更容易找到.
在一天结束时,它只是其他静态方法的语法糖,但就像买房子一样:"位置,位置,位置!" 如果它挂在类型上,人们会发现它!
我认为扩展方法在编写代码时有很多帮助,如果你将扩展方法添加到基本类型中,你会在intellisense中快速获得它们.
我有一个格式提供程序来格式化文件大小.要使用它,我需要写:
Console.WriteLine(String.Format(new FileSizeFormatProvider(), "{0:fs}", fileSize));
创建扩展方法我可以写:
Console.WriteLine(fileSize.ToFileSize());
更清洁,更简单.
我遇到的扩展方法还有两个好处:
一个流畅的接口可以封装在一个静态的扩展方法类中,从而实现核心类和它的流畅扩展之间的关注点分离; 我已经看到了实现更高的可维护性
扩展方法可以挂起接口,从而允许您指定合同(通过接口)和相关的一系列基于接口的行为(通过扩展方法),再次提供关注点分离.
我对扩展方法的一些最佳用途是能够:
扩展第三方对象(无论是商业的还是我公司内部的,但由一个单独的组管理)的功能,在许多情况下将被标记为sealed
.
为接口创建默认功能,而无需实现抽象类
举个例子,IEnumerable
.虽然它有丰富的扩展方法,但我发现它没有实现通用的ForEach方法很烦人.所以,我自己做了:
public void ForEach(this IEnumerable enumerable, Action action) { foreach ( var o in enumerable ) { action(o); } }
瞧,IEnumerable
无论实现类型如何,我的所有对象,以及我是否编写它或其他人现在都ForEach
通过在我的代码中添加适当的"using"语句来实现方法.
使用扩展方法的一个重要原因是LINQ.没有扩展方法,你在LINQ中可以做的很多事情都会非常困难.Where(),Contains(),Select扩展方法意味着在不改变其结构的情况下将更多功能添加到现有类型.
关于扩展方法的优点有很多答案; 如何解决这些弊端?
最大的缺点是,如果在同一个上下文中有常规方法和具有相同签名的扩展方法,则不会出现编译器错误或警告.
假设您创建了一个应用于特定类的扩展方法.然后有人在该类本身创建一个具有相同签名的方法.
您的代码将编译,您甚至可能不会收到运行时错误. 但是你不再像以前那样运行相同的代码了.
Greg Young在CodeBetter上展示了流畅的界面和上下文敏感性