我正在寻找在C#应用程序中使用扩展方法而非静态实用程序类的一些优缺点。
例如,扩展方法列中的一个加号是通过类名调用而不是像“StringUtils”那样的方便。但是,它可能会模糊框架内部与非框架之间的界限。
答案 0 :(得分:49)
我想说 pro 是它模糊了框架中的内容和不是内容之间的界限:您可以像框架代码一样自然地使用自己的代码,对框架类型进行操作
扩展方法当然不应该被任意使用 - 它不像所有静态方法应该成为扩展方法。
我试着将其视为该方法是否在逻辑上“操作”其第一个参数。如果你能够将它作为实例方法包含在内,它作为实例方法是否有意义?
你可能不知道的“con”:如果扩展类型后来添加了一个适用于相同参数的同名实例方法,那么你的调用代码将在下次重新编译时透明地开始调用该实例方法。例如,Stream
在.NET 4中获得CopyTo
...我之前编写了一个CopyTo
扩展方法,然后不会被调用。没有警告说这种情况正在发生,所以你必须保持警惕。
有一点需要注意:扩展方法已经存在很长时间,以至于最佳实践无法真正建立起来。你应该仔细权衡所有意见(甚至 - 或者特别是 - 我自己的意见)。
答案 1 :(得分:12)
在一天结束时,两种方法都使用静态方法。
之间的唯一区别string foo = "bob";
StringUtils.DoSomething(foo);
和
string foo = "bob";
foo.DoSomething();
是语法糖。它归结为个人偏好和编码标准。有时,方法名称可能足够描述,无法保证看到静态类名称。其他时候包含类名更有意义。
最后,扩展方法也可以作为静态方法调用!
string foo = "bob";
StringExtensions.DoSomething(foo);
以上使用与第二个示例中相同的代码,但调用方式不同。考虑到最后这个问题,您可以真正创建静态实用程序类作为扩展方法,然后根据需要调用它们。
答案 2 :(得分:4)
我个人喜欢Extension方法提供的readabilty和链调用(隐式提供可读性)。
1) Readability:
bool empty = String.IsNullOrEmpty (myString)
//in comparison to
bool empty = myString.IsNullOrEmpty ();
2) Chain calls:
var query = Enumerable.Range(0, 10)
.Where(x => x % 2 == 0)
.Reverse();
//instead of
var query = Enumerable.Reverse(Enumerable.Where(Enumerable.Range(0, 10), x => x % 2 == 0));
Con是你的扩展方法可以被实例成员覆盖,如果你不小心这样做了。我个人不喜欢这个。至少编译器应该尖叫,如果它发生在同一个程序集中。