扩展方法与继承

发布于 2024-07-27 12:21:41 字数 69 浏览 7 评论 0原文

是否有经验法则可以帮助确定在什么情况下使用哪个? 大多数时候我应该选择其中之一而不是其他吗?

谢谢!

Are there rules of thumb that help determine which to use in what case? Should I prefer one over the other most times?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

混浊又暗下来 2024-08-03 12:21:41

扩展方法很有用,但它们比常规方法更难通过 IDE 发现,因为它们不附加到原始类,并且没有任何线索表明它们的代码可能驻留在何处。 有一些

通常,如果您只是向众所周知、常用的类或接口(例如 .Net 基类)添加功能,而您无权访问其代码,则通常会使用扩展方法。 扩展方法还具有这样的约束:您不仅必须拥有原始程序集,还必须拥有其中包含扩展方法的程序集,而代码的使用者必须能够理解该程序集。

使用继承将允许您添加、删除或覆盖功能,并确保在构建类时它始终与类一起存在。

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 suggestions as 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.

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.

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.

等待我真够勒 2024-08-03 12:21:41

当您想要提供跨各种类型的实现时,应该使用扩展方法,这些类型应该共享相同的行为,但否则会有所不同。 这就是为什么您会看到扩展方法在接口上大量使用,因为它是一个非常强大的工具,可以确保接口的任何给定实现都具有给定行为的相同实现。

例如,Skip 和 Take 扩展方法。

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.

舞袖。长 2024-08-03 12:21:41

嗯...你不能总是使用继承。 例如,String 是一个密封类。 在这些情况下,扩展方法才真正发挥作用。

一般来说,扩展方法最适合您可能放入静态类中但针对特定类型的实例进行操作的小实用程序。 字符串是一个很好的例子——几乎每个人都有自己的小字符串扩展方法来对字符串进行少量操作。

扩展方法的另一个好地方是针对枚举。 我几乎总是针对我创建的任何 [Flags] 枚举包含一个 HasFlag 扩展方法。

Well... you can't always use inheritance. String, for example, is a sealed class. It's in those cases where an extension method really shines.

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.

も星光 2024-08-03 12:21:41

只要有可能,请使用继承而不是扩展方法

编辑

我更喜欢保持简短,但我当然会回答后续问题。

在可以继承的情况下,即未密封的类,它几乎总是比扩展方法更好的选择。 事实上,这就是 最佳实践文档,womp 引用说。 它的标题包括“警惕扩展方法”、“在扩展您不拥有的类型之前三思而后行”和“优先选择接口扩展而不是类扩展”。 换句话说,它只是更详细地说明了我的一句台词所做的事情。

这篇文章确实给出了详细的原因,但最重要的是,这就是扩展方法的设计用途。 它们在游戏后期作为一点语法糖被添加到语言中,以允许 MS 嵌入 LINQ,而无需返回并重新发明轮子。 这是它们的优点的典型例子。 另一个很好的例子是添加实用方法,例如:

public static string FormatWith(this string format, params object[] args)
{ return string.Format(CultureInfo.InvariantCulture, format, args); }

请注意,在这种情况下,扩展方法是完成此附加功能的唯一方法,因为字符串是密封的。

至于组合优于继承,虽然这是老生常谈,但我在这里看不到相关性。 无论我们使用扩展方法还是继承,目标都是更改接口以允许使用另一种方法。 该方法的实现方式,无论是通过组合、泛型还是其他技术,都是正交的。

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 document that 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.

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:

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.

东走西顾 2024-08-03 12:21:41

它们非常不同,例如 LINQ 标准查询运算符是扩展方法的一个很好的例子,这些方法应该很难通过继承来实现,但是如果您有权访问类并且可以更改源,那么使用继承会更好,
编辑
这是我在这里找到的一些规则C# 3.0 特性:扩展方法

  • 扩展方法不能用于覆盖现有方法 与
  • 实例方法同名和签名的扩展方法不会被调用
  • 扩展方法的概念不能应用于字段、属性或事件
  • 谨慎使用扩展方法......过度使用可能是一件坏事!

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

  • 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!
给不了的爱 2024-08-03 12:21:41

我会坚持继承,除非扩展方法主要是为了扩展密封类或创建特定于范围的扩展而设计的。 另请记住,它们是静态的,因此如果您需要在其他类中重写这些方法和行为,则无法真正使用扩展。

扩展方法确实有一个非常好的特性,那就是其实现的固有优势。 由于它们是静态方法,因此您可以在 null 对象上调用它们。

例如:

string a = null;
return a.IfNullOrEmpty("Default Value");

像这样的实现很棒,尽管它们在技术上只是语法糖。 恕我直言,任何能让你的代码更干净、更具可读性的东西都是很棒的。

虽然我不喜欢它们并不是真正被发现的。 如果我将该代码从一个类复制到另一个类,那么我将不得不搜索定义它的名称空间。

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.

蓝颜夕 2024-08-03 12:21:41

这实际上取决于您需要解决的问题,在大多数情况下,类继承和接口自然比扩展方法更有意义,因此应该是首选。

另一方面,扩展允许您创建不仅仅应用于一个类的有用方法 - 否则使用继承会更加麻烦>,如果不是的话几乎不可能实现。

最后但并非最不重要的一点是,扩展允许您扩展.NET Framework的内置类以及第三方类即使您不拥有或无权访问源代码。

以下是一些使用扩展方法的示例:


LinqPad 使用扩展方法,例如 .Dump() 方法,您可以使用该方法将每种对象的内容转储(打印)到输出窗口。


.NET 框架本身在许多地方使用扩展方法,例如在 Linq:

public static TSource FirstOrDefault<TSource>(this 
                        System.Collections.Generic.IEnumerable<TSource> source)

返回任何对象类型的任何可枚举集合的第一个元素或默认值。


扩展方法比继承更好的示例如下:
假设您想创建一个能够创建克隆 任何现有对象的(复制)。 使用扩展(和泛型,加上反射),您可以做到这样

It really depends on the problem you need to solve, in most situations class inheritance and interfaces make naturally more sense than extension methods and thus should be preferred.

On the other hand, Extensions allow you to create useful methods applying not just to one class - which would otherwise be much more cumbersome to do with inheritance, if not almost impossible to achieve.

Last but not least, Extensions allow you to extend .NET Framework's builtin classes as well as 3rd party classes, even if you don't own or have no access to the sourcecode.

Here are some examples where extension methods are used for good reasons:


LinqPad uses extension methods, for example the .Dump() method with which you can dump (print) the contents of every kind of object to the output window.


The .NET framework itself uses extension methods in many places, for example in Linq:

public static TSource FirstOrDefault<TSource>(this 
                        System.Collections.Generic.IEnumerable<TSource> source)

which returns the first element or default of any enumerable collection of any object 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.

热情消退 2024-08-03 12:21:41

扩展方法破坏了良好的面向对象设计。 说它们应该用于您无权访问代码库的密封类是荒谬的。 被密封且您无权访问的类可能出于某种原因(性能、线程安全)而被密封,并且盲目地将功能标记到这些类是非常危险的。 总有一种方法可以以纯面向对象的方式实现装饰器模式,而不这样做会使代码更难以阅读、维护和重构。 根据经验,如果一种语言的某个功能听起来很糟糕,那么就应该避免它。 我确信您可以找到一个扩展方法很有用的示例,但事实是该功能会被那些受过最少 OO 培训的开发人员滥用。

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.

幻想少年梦 2024-08-03 12:21:41

MSDN

C# 编程指南 它说:

一般指南

一般来说,我们建议您谨慎地实现扩展方法,并且仅在必要时才实现。 只要有可能,必须扩展现有类型的客户端代码应该通过创建从现有类型派生的新类型来实现。 有关详细信息,请参阅继承(C# 编程指南)。

当使用扩展方法来扩展无法更改其源代码的类型时,您将面临这样的风险:类型实现的更改将导致扩展方法中断。

MSDN

In the page on extension methods in the C# programming guide it says:

General Guidelines

In general, we recommend that you implement extension methods sparingly and only when you have to. Whenever possible, client code that must extend an existing type should do so by creating a new type derived from the existing type. For more information, see Inheritance (C# Programming Guide).

When using an extension method to extend a type whose source code you cannot change, you run the risk that a change in the implementation of the type will cause your extension method to break.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文