C# 扩展方法与继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1132262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extension methods versus inheritance
提问by djcouchycouch
Are there rules of thumb that help determine which to use in what case? Should I prefer one over the other most times?
是否有经验法则可以帮助确定在什么情况下使用哪个?大多数时候我应该更喜欢一个吗?
Thanks!
谢谢!
采纳答案by womp
Extension methods are useful, but they are harder to discover through the IDE than regular methods, since they are not attached to the original class and there are no clues as to where the code for them might reside. There are some best practice suggestionsas to where to put them and how to name them, but these are only guidelines and there is no guarantee that someone will follow them.
扩展方法很有用,但它们比常规方法更难通过 IDE 发现,因为它们不附加到原始类,并且没有关于它们的代码可能驻留在何处的线索。关于将它们放在哪里以及如何命名它们,有一些最佳实践建议,但这些只是指导方针,并不能保证有人会遵循它们。
Usually you would use extension methods if you are only adding functionality to a well known, well used class or interface such as the .Net base classes, that you don't have access to the code for. Extension methods also have the constraint in that you not only have to have the original assembly, you have to have the assembly with the extension methods in it, which must be understood by consumers of your code.
通常,如果您只是向众所周知的、使用良好的类或接口(例如 .Net 基类)添加功能,而您无权访问其代码,则通常会使用扩展方法。扩展方法还具有约束条件,即您不仅必须拥有原始程序集,还必须拥有包含扩展方法的程序集,您的代码的使用者必须理解这些。
Using inheritance will allow you to add, remove or override functionality, and ensure that it is always present with the class when you build it.
使用继承将允许您添加、删除或覆盖功能,并确保在构建类时它始终存在于类中。
回答by Steven Sudit
Whenever possible, use inheritance instead of extension methods.
尽可能使用继承而不是扩展方法。
edit
编辑
I prefer to keep this short and simple, but I will of course answer follow-up questions.
我更喜欢保持简短,但我当然会回答后续问题。
In the cases where inheritance is possible, which is to say classes that are not sealed, it is almost always a better option than extension methods. In fact, this is what the best practices documentthat womp referenced says. It has headings such as "Be wary of extension methods", "Think twice before extending types you don't own", and "Prefer interface extensions over class extensions". In other words, it just says what my one-liner did, with greater detail.
在可以继承的情况下,即没有密封的类,它几乎总是比扩展方法更好的选择。事实上,womp 引用的最佳实践文档就是这么说的。它有诸如“警惕扩展方法”、“在扩展您不拥有的类型之前要三思”和“优先使用接口扩展而不是类扩展”等标题。换句话说,它只是更详细地说明了我的 one-liner 所做的事情。
The article does give detailed reasons, but the bottom line is that this is how extension methods were designed to be used. They were added to the language late in the game as a bit of syntactic sugar to allow MS to wedge in LINQ without having to go back and reinvent the wheel. This is the canonical example of what they are good for. Another good example is adding utility methods, such as:
这篇文章确实给出了详细的原因,但最重要的是,这就是扩展方法的设计用途。它们在游戏后期被添加到语言中,作为一种语法糖,让 MS 能够融入 LINQ,而无需回去重新发明轮子。这是它们的优点的典型示例。另一个很好的例子是添加实用方法,例如:
public static string FormatWith(this string format, params object[] args)
{ return string.Format(CultureInfo.InvariantCulture, format, args); }
Note that, in this case, extension methods were the only way to accomplish this additional feature, since strings are sealed.
请注意,在这种情况下,扩展方法是实现此附加功能的唯一方法,因为字符串是密封的。
As for composition over inheritance, while this is a truism, I fail to see the relevance here. Whether we're using extension methods or inheritance, the goal is to change the interface to allow another method. How this method is implemented, whether by composition, generics or some other technique, is orthogonal.
至于组合而不是继承,虽然这是老生常谈,但我看不到这里的相关性。无论我们使用扩展方法还是继承,目标都是更改接口以允许使用其他方法。这个方法是如何实现的,无论是通过组合、泛型还是其他一些技术,都是正交的。
回答by Arsen Mkrtchyan
They are very different, for example LINQ standard query operators are great example of extension methods that should be difficult to implement with inheritance, but if you have access to class and can change source it will be better to use inheritance,
EDIT
and here is some rules that I find here C# 3.0 Features: Extension Methods
它们非常不同,例如 LINQ 标准查询运算符是扩展方法的一个很好的例子,应该很难通过继承来实现,但是如果您可以访问类并且可以更改源,那么使用继承会更好,
编辑
,这里有一些我在这里找到的规则C# 3.0 特性:扩展方法
- Extension methods cannot be used to override existing methods
- An extension method with the same name and signature as an instance method will not be called
- The concept of extension methods cannot be applied to fields, properties or events
- Use extension methods sparingly....overuse can be a bad thing!
- 扩展方法不能用于覆盖现有方法
- 与实例方法具有相同名称和签名的扩展方法将不会被调用
- 扩展方法的概念不能应用于字段、属性或事件
- 谨慎使用扩展方法......过度使用可能是一件坏事!
回答by Joseph
Extension methods should be used when you want to provide an implementation across a variety of types that should share the same behavior, but would otherwise be disimilar. That's why you see extension methods being used on interfaces a lot, because it's a very powerful tool to ensure that any given implementation of an interface will have the same implementation of a given behavior.
当您想提供跨多种类型的实现时,应该使用扩展方法,这些类型应该共享相同的行为,但否则会不同。这就是为什么您会在接口上看到大量使用扩展方法的原因,因为它是一个非常强大的工具,可以确保接口的任何给定实现都将具有给定行为的相同实现。
For example, the Skip and Take extension methods.
例如,Skip 和 Take 扩展方法。
回答by Randolpho
Well... you can't always useinheritance. String
, for example, is a sealed class. It's in those cases where an extension method really shines.
嗯……你不能总是使用继承。String
例如,是一个密封类。在那些情况下,扩展方法真正发挥作用。
In general, extension methods are best for little utilities that you might otherwise put into a static class, but that operate against an instance of a particular type. Strings are a great example -- almost everyone has their own little string extension methods to do little operations on a string.
通常,扩展方法最适合您可能会放入静态类中但针对特定类型的实例操作的小实用程序。字符串就是一个很好的例子——几乎每个人都有自己的小字符串扩展方法来对字符串做一些小操作。
Another great place for extension methods is against enumerations. I almost always include a HasFlag
extension method against any [Flags]
enumerations I create.
扩展方法的另一个好地方是反对枚举。我几乎总是包含HasFlag
针对[Flags]
我创建的任何枚举的扩展方法。
回答by Brian Rudolph
I would stick to inheritance except in the cases that extension methods were primarily designed for - extending sealed classes or creating scope-specific extensions. Also remember that they are static, so if these are methods and behaviours that you would need to override in other classes, you can't really use extensions.
我会坚持继承,除非扩展方法主要设计用于扩展密封类或创建特定于范围的扩展。还要记住,它们是静态的,所以如果这些是您需要在其他类中覆盖的方法和行为,您就不能真正使用扩展。
Extension methods do have one really great feature that is an inherent benefit of their implementation. Since they are static methods, you can call them on a null object.
扩展方法确实有一个非常棒的特性,那就是它们实现的内在好处。由于它们是静态方法,您可以在空对象上调用它们。
For instance:
例如:
string a = null;
return a.IfNullOrEmpty("Default Value");
Implementations like this are great, though they are technically just syntactical sugar. IMHO, anything that keeps your code cleaner and more readable is great.
像这样的实现很棒,尽管它们在技术上只是语法糖。恕我直言,任何能让你的代码更清晰、更具可读性的东西都很棒。
Though I don't like that they aren't really discoverable. If I copy that code from one class to another, i would then have to search for the namespace in which it was defined.
虽然我不喜欢它们,但它们并不能真正被发现。如果我将该代码从一个类复制到另一个类,则必须搜索定义它的命名空间。
回答by ComeIn
Extension methods break good OO design. To say they should be used on sealed classes that you do not have access to the code base is ridiculous. Classes that are sealed and you do not have access to are probably sealed for a reason (performance, thread safety) and to tag functionality blindly to these classes is down right dangerous. There is always a way of implementing the decorator pattern in a pure OO way and to not do it that way makes the code harder to read, maintain and refactor. As a rule of thumb, if a feature of a language smells bad then it should be avoided. I'm sure you could find one example where extension methods are useful however the truth is that the feature will be abused by those developers with minimal OO training.
扩展方法破坏了良好的 OO 设计。说它们应该用于您无法访问代码库的密封类是荒谬的。密封且您无权访问的类可能出于某种原因(性能、线程安全)而被密封,并且盲目地将功能标记到这些类是非常危险的。总是有一种方法可以以纯面向对象的方式实现装饰器模式,不这样做会使代码更难阅读、维护和重构。根据经验,如果一种语言的某个特性闻起来很糟糕,那么就应该避免它。我相信您可以找到一个扩展方法很有用的示例,但事实是该功能会被那些接受过最少 OO 培训的开发人员滥用。
回答by Matt
It really depends on the problem you need to solve, in most situations class inheritance and interfacesmake naturally more sense than extension methods and thus should be preferred.
这实际上取决于您需要解决的问题,在大多数情况下,类继承和接口自然比扩展方法更有意义,因此应该首选。
On the other hand, Extensionsallow you to create useful methods applying not just to oneclass - which would otherwise be much more cumbersome to do with inheritance, if not almost impossible to achieve.
另一方面,扩展允许您创建有用的方法,不仅适用于一个类 - 否则,如果不是几乎不可能实现,继承会更加麻烦。
Last but not least, Extensionsallow you to extend .NET Framework's builtin classesas well as 3rd party classes,even if you don't own or have no access to the sourcecode.
最后但并非最不重要的是,扩展允许您扩展.NET Framework 的内置类以及第 3 方类,即使您不拥有或无法访问源代码。
Here are some examples where extension methods are used for good reasons:
以下是一些出于充分理由使用扩展方法的示例:
LinqPaduses extension methods, for example the .Dump()
method with which you can dump (print) the contents of every kind of object to the output window.
LinqPad使用扩展方法,例如.Dump()
您可以将每种对象的内容转储(打印)到输出窗口的方法。
The .NET frameworkitself uses extension methods in many places, for example in Linq:
在.NET框架本身使用扩展方法在很多地方,例如在LINQ的:
public static TSource FirstOrDefault<TSource>(this
System.Collections.Generic.IEnumerable<TSource> source)
which returns the first element or default of anyenumerable collection of anyobject type.
它返回任何对象类型的任何可枚举集合的第一个元素或默认值。
An example, where extension methods are better than inheritance is the following: Say you want to create a method which is able to create a clone(copy)of any existing object. With Extensions (and generics, plus reflection) you can do it this way.
一个扩展方法比继承更好的例子如下:假设你想创建一个方法,它能够创建任何现有对象的克隆(副本)。随着扩展(和仿制药,加上反射)你能做到这样。