Is it acceptable to use extension methods on a class which you can modify

I've recently been toying with the idea of using extension methods to implement helper utilities on classes which I control (ie, are in the same program and I can modify). The rationale behind it is that many times, these helper utilities are used in very specific scenarios and don't require access to the classes internal values.

For instance, let's say I have a StackExchange class. It'd have methods like PostQuestion and Search and AnswerQuestion .

Now, what if I wanted to manually calculate my reputation to ensure that StackOverflow isn't cheating me. I'd implement something along the lines of:

int rep=0;
foreach(var post in StackExchangeInstance.MyPosts)

I could add a method to the StackExchange class, but it doesn't require any internals, and it is only used from one or two other portions of the program.

Now imagine if instead you had 10 or 20 of these specific helper methods. Useful in a certain scenario for sure, but definitely not for the general case. My idea is changing something like

public static RepCalcHelpers
  public static int CalcRep(StackExchange inst){ ... }

To something like

namespace Mynamespace.Extensions.RepCalculations
  public static RepCalcExtensions
    public static int CalcRep(this Stackexchange inst){...}

Note the namespace. I'd ideally use this to group extension methods within a certain scenario. For instance, "RepCalculations", "Statistics", etc.

I've tried searching for if this type of pattern is at all heard of, and haven't found any evidence of extension methods being used for anything but classes you can't modify.

What shortcomings are there with this "pattern"? Should I instead stick to inheritance or composition, or just a good ol' static helper class for this?

I would read the section of Framework Design Guidelines on Extension methods. Here is a post by one of the authors for the 2nd edition. The use case you are describing (specialized helper methods) is cited by Phil Haack as a valid use for extension methods with the drawback that it requires extra knowledge of the API to find those "hidden" methods.

Not mentioned in that post but recommended in the book is that the extension methods go into a separate namespace from the extended class. Otherwise, they will always appear with intellisense and there is no way to turn them off.

I think I have seen this pattern somewhere else. It could quite confusing, but also quite powerful. That way you can provide a class in a library and a set of extension methods in separate namespace. Then whoever is using your library can choose to import namespace with your extension methods or provide their own extension methods.

A good candidate for this pattern would be if you have some extension methods used for unit testing only (eg to compare if two objects are equal in a sense you'd need for unit tests only).

You seem to be making the comparison that the extension method is equivalent to a public instance method. It's really not.

An extension method is just a public static utility method that happens to have a more convenient syntax for being called.

So first we have to ask ourselves, it it appropriate for this method to be an instance method of the class itself or is it more appropriate for it to be a static method of an external class. The fact that very few users of the class need this functionality because it's highly localized and not truly behavior that the class itself performs but rather behavior performed on the class by an external entity means that it's appropriate for it to be static. The primary drawback is that it's behavior that is potentially harder to find if someone has a User and wants to recalculate their rep. Now, in this particular case it's a bit on the fence, and you could go the other way, but I am leaning towards static method.

Now that we've decided it should be static it's an entirely separate question of whether or not it should be an extension method or not. This is much more subjective and goes into the personal preference realm. Are the methods likely to be chained? If so, extension methods chain much more nicely than nested calls to static methods. Is it likely to be used a lot in the files that do use it? If yes, extension methods are likely going to simplify the code a bit, if not, it doesn't really help as much, or even hurts. To the toy example I'd probably say that I personally wouldn't, but I wouldn't have any problem at all with someone who did (after all you can still use an extension method as if it's a regular public static method syntax wise). For a non-toy example, it's mostly a case-by-case decision. A key point is to be careful what classes you extend, and to ask yourself if a user is willing to clutter the Intellisense of a type just to call a methods slightly more conveniently (this again gets back to how much it's used per file it's used in).

It's also worth mentioning that there are a few edge cases where extension methods can be more powerful than instanced methods. In particular through utilizing type inference. With a regular instance method it's easy enough to accept a type or any sub-type of that type, but sometimes it's useful to return whatever the type is that was passed in instead of the parent type. This is used particularly in fluent APIs. This isn't a very common example though, and is only loosely related to your question, so I won't expand on that.


上一篇: ANTLR v4,JavaLexer和JavaParser返回null作为分析树

下一篇: 在可以修改的类上使用扩展方法是可以接受的