Jer*_*rry 83 c# extension-methods
C#的"非信徒"问我扩展方法的目的是什么.我解释说,然后您可以向已定义的对象添加新方法,尤其是当您不拥有/控制原始对象的源时.
他提出"为什么不在自己的课堂上添加一种方法?" 我们一直在四处走动(以一种很好的方式).我的一般回答是,它是工具带中的另一个工具,他的回答是它是一种无用的工具浪费......但我认为我会得到一个更"开明"的答案.
有哪些场景你使用了你不能(或不应该)使用的方法添加到你自己的类上的扩展方法?
And*_*are 83
扩展方法的唯一优点是代码可读性.而已.
扩展方法允许您这样做:
foo.bar();
Run Code Online (Sandbox Code Playgroud)
而不是这个:
Util.bar(foo);
Run Code Online (Sandbox Code Playgroud)
现在C#中有很多东西都是这样的.换句话说,C#中有许多功能似乎微不足道,并且本身并没有很大的好处.然而,一旦开始将这些功能组合在一起,您就会开始看到比其各部分总和更大的东西.LINQ从扩展方法中获益很大,因为如果没有它们,LINQ查询几乎是不可读的.LINQ可以在没有扩展方法的情况下实现,但不实用.
扩展方法很像C#的部分类.他们自己并不是很有帮助,而且似乎微不足道.但是当你开始使用需要生成代码的类时,部分类开始变得更有意义.
Bri*_*ian 33
不要忘记工具!当你在Foo类型上添加扩展方法M时,你会在Foo的intellisense列表中得到'M'(假设扩展类在范围内).这使得'M'比MyClass.M(Foo,...)更容易找到.
在一天结束时,它只是其他静态方法的语法糖,但就像买房子一样:"位置,位置,位置!" 如果它挂在类型上,人们会发现它!
Edu*_*añó 33
我认为扩展方法在编写代码时有很多帮助,如果你将扩展方法添加到基本类型中,你会在intellisense中快速获得它们.
我有一个格式提供程序来格式化文件大小.要使用它,我需要写:
Console.WriteLine(String.Format(new FileSizeFormatProvider(), "{0:fs}", fileSize));
Run Code Online (Sandbox Code Playgroud)
创建扩展方法我可以写:
Console.WriteLine(fileSize.ToFileSize());
Run Code Online (Sandbox Code Playgroud)
更清洁,更简单.
Dav*_*ert 29
我遇到的扩展方法还有两个好处:
Jon*_*jap 26
我对扩展方法的一些最佳用途是能够:
sealed.举个例子,IEnumerable<T>.虽然它有丰富的扩展方法,但我发现它没有实现通用的ForEach方法很烦人.所以,我自己做了:
public void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach ( var o in enumerable )
{
action(o);
}
}
Run Code Online (Sandbox Code Playgroud)
瞧,IEnumerable<T>无论实现类型如何,我的所有对象,以及我是否编写它或其他人现在都ForEach通过在我的代码中添加适当的"using"语句来实现方法.
Ray*_*sen 12
使用扩展方法的一个重要原因是LINQ.没有扩展方法,你在LINQ中可以做的很多事情都会非常困难.Where(),Contains(),Select扩展方法意味着在不改变其结构的情况下将更多功能添加到现有类型.
关于扩展方法的优点有很多答案; 如何解决这些弊端?
最大的缺点是,如果在同一个上下文中有常规方法和具有相同签名的扩展方法,则不会出现编译器错误或警告.
假设您创建了一个应用于特定类的扩展方法.然后有人在该类本身创建一个具有相同签名的方法.
您的代码将编译,您甚至可能不会收到运行时错误. 但是你不再像以前那样运行相同的代码了.
我想支持这里的其他答案,这些答案提到提高代码可读性是扩展方法背后的一个重要原因。我将从两个方面来演示这一点:方法链接与嵌套方法调用,以及带有无意义静态类名的 LINQ 查询的混乱。
我们以这个 LINQ 查询为例:
numbers.Where(x => x > 0).Select(x => -x)
Run Code Online (Sandbox Code Playgroud)
和Where都是Select扩展方法,在静态类中定义Enumerable。因此,如果扩展方法不存在,并且这些是普通的静态方法,那么最后一行代码基本上必须如下所示:
Enumerable.Select(Enumerable.Where(numbers, x => x > 0), x => -x)
Run Code Online (Sandbox Code Playgroud)
看看刚才的查询有多糟糕。
其次,如果您现在想引入自己的查询运算符,那么您自然无法Enumerable像所有其他标准查询运算符一样在静态类中定义它,因为Enumerable是在框架中并且您无法控制该类。因此,您必须定义自己的包含扩展方法的静态类。然后您可能会收到如下查询:
Enumerable.Select(MyEnumerableExtensions.RemoveNegativeNumbers(numbers), x => -x)
// ^^^^^^^^^^^^^^^^^^^^^^
// different class name that has zero informational value
// and, as with 'Enumerable.xxxxxx', only obstructs the
// query's actual meaning.
Run Code Online (Sandbox Code Playgroud)