4

Recently I asked a question about how to clean up what I considered ugly code. One recommendation was to create an Extension Method that would perform the desired function and return back what I wanted. My first thought was 'Great! How cool are Extensions...' but after a little more thinking I am starting to have second thoughts about using Extensions...

My main concern is that it seems like Extensions are a custom 'shortcut' that can make it hard for other developers to follow. I understand using an Extension can help make the code syntax easier to read, but what about following the voice behind the curtain?

Take for example my previous questions code snippet:

if (entry.Properties["something"].Value != null)
  attribs.something = entry.Properties["something"].Value.ToString();

Now replace it with an Extension:

public static class ObjectExtensions
{
    public static string NullSafeToString(this object obj)
    {
        return obj != null ? obj.ToString() : String.Empty;
    }
}

and call using the syntax:

attribs.something = entry.Properties["something"].Value.NullSafeToString();

Definetely a handy way to go, but is it really worth the overhead of another class object? And what happens if someone wants to reuse my code snippet but doesn't understand Extension? I could have just as easily used the syntax with the same result:

attribs.something = (entry.Properties["something"].Value ?? string.Empty).ToString()

So I did a little digging and found a couple of articles that talked about the pros/cons of using Extensions. For those inclined have a look at the following links:

MSDN: Extension Methods

Extension Methods Best Practice

Extension Methods

I can't really decide which is the better way to go. Custom Extensions that do what I want them to do or more displayed code to accomplish the same task? I would be really interested in learning what 'real' developers think about this topic...

4

5 回答 5

20

Personally I think the "problems" of extension method readability are vastly overstated. If you concentrate on making your code easy to read in terms of what it's doing, that's more important most of the time than how it's doing it. If the developer wants to trace through and find out what's actually happening behind the scenes, they can always click through to the implementation.

My main problem with extension methods is their discovery method - i.e. via a specified namespace instead of a specified class. That's a different matter though :)

I'm not suggesting that you put in extension methods arbitrarily, but I would seriously consider how often you need to know how every expression in a method works vs skimming through it to see what it does in broader terms.

EDIT: Your use of terminology may be misleading you slightly. There's no such thing as an "extension object" - there are only "extension methods" and they have to exist in static types. So you may need to introduce a new type but you're not creating any more objects.

于 2009-02-15T21:10:03.540 回答
6

[OP] Definetely a handy way to go, but is it really worth the overhead of another class object?

No extra class object is created in this scenario. Under the hood, extension methods are called no differently than a static method. There is an extra metadata entry for the extension method container but that is pretty minimal.

[OP] And what happens if someone wants to reuse my code snippet but doesn't understand Extension Objects?

Then it would be a good time to educate them :). Yes, there is the risk that a new developer may not be comfortable with extension methods to start. But this is hardly an isolated feature. It's being used more and more in all of the code samples I'm seeing internally and on the web. It's something that is definitely worth while for a developer to learn. I don't think it fits into the category of "to esoteric to expect people to know"

于 2009-02-15T21:09:43.197 回答
5

The only serious weirdness to deal with in Extension methods are:

  1. They do not have to cause a null reference exception if the left hand side (the object on which it appears you are invoking a method) is null.
    • can sometimes be useful, but is contrary to expectations as such should be used with extreme caution.
  2. They are not accessible through reflection on the classes/interfaces to which they apply.
    • generally not a problem, but worth keeping in mind.
  3. Name collisions with other extension methods involve a lengthy resolution rule sequence
    • if you care the sequence is to prefer:
      1. Extension methods defined inside the current module.
      2. Extension methods defined inside data types in the current namespace or any one of its parents, with child namespaces having higher precedence than parent namespaces.
      3. Extension methods defined inside any type imports in the current file.
      4. Extension methods defined inside any namespace imports in the current file.
      5. Extension methods defined inside any project-level type imports.
      6. Extension methods defined inside any project-level namespace imports.
于 2009-02-15T21:35:19.593 回答
2

[OP] And what happens if someone wants to reuse my code snippet but doesn't understand Extension Objects?

The extension methods will not show in the intellisense for the object if the assembly that implements them is not references in the project. Your code snippet will also not compile. That could potentially create a bit of a confusion to the other developer.

If the extension method assembly is referenced, it will show in the intellisense, but it will be not mentioned in the documentation for the object. This could potentially cause a bit of confusion as well.

However, as @JaredPar mentioned, the extension methods as a technique are used more and more and I would expect most of the C# programmers to know about them. Thus, I wound't be too worried about any potential confusion.

于 2009-02-15T21:25:16.387 回答
0

C# Extensions is an additional "tool" provided by .Net in order to help you write your code a little bit nicer. Another advantage of them is, that they handle null. Although they seem very usable, I try to use them only in certain cases that will really tidy up my code, because they are not standard coding methods and they stand a little bit seperate from other classes as they have to be in static classes and are static themselves.

Let's say their implementation is a little bit untidy, but their use is made tidier.

It is also important to mention that they only exist in C# and VB.Net (Java doesn't have Extensions). Another important fact is that Extensions have no priority over standard methods, meaning that if a method is implemented in a class with the same name as an extension method on the same class, then the first method is the one that will be called and not the extension method.

Below there are three cases where I often use them, why I use them and alternative solutions that would solve the same problem:

1. To implement specific methods for generic classes: I have a generic type, let's say a collection List<T>. I want to do a method that applies only to a specific kind of list. Let's say a method that creates a union from a list of strings using a seperator ("A", "B", "C", " sep " --> "A sep B sep C"):

public static string union(this List<string> stringList, String seperator)
{
   String unionString = "";
   foreach (string stringItem in stringList) {
      unionString += seperator + stringItem; }
   if (unionString != "") { 
      unionString = unionString.Substring(seperator.Length); }
   return unionString;
}

In case I didn't want to use an extension, I would have to create a new class "StringCollection : List<string>" and implement my method there. This is mainly not a problem and it is actually better in most cases, but not in all cases. If for example you are receiving all your data in lists of strings in many cases, you don't have to convert those lists in StringCollections each time you want to use union, but use an extension instead.

2. To implement methods that need to handle null: I need a method to convert an object to a string without throwing an exception in case the object is null

public static String toStringNullAllowed(this Object inputObject)
{
   if (inputObject == null) { return null; }
   return inputObject.ToString();
}

In case I didn't want to use an extension, I would have to create a class (probably static), for example StringConverter, which will do the same job, with more words than a simple myObject.toStringNullAllowed();

3. To extend value types or sealed classes: Value types such as int, float, string, etc as well as sealed classes (classes that cannot be inherited) cannot be extended through inheritance. Below you can see an example of extending integers to be able to be converted to x-digit Strings (for example integer 34, digits 5 --> "00034"):

public static String toXDigit(this int inputInteger, int x)
{
   String xDigitNumber = inputInteger.ToString();
   while (xDigitNumber.Length < x) { xDigitNumber = "0" + xDigitNumber; }
   return xDigitNumber;
}

Again an alternative solution would be a static class (like a toolbox), let's say "Math".

  • In that case you would write: Math.toXDigit(a, x);
  • While with the extension method: a.toXDigit(x);

The extension method looks better and is more understandable, like speaking English

To conclude, I guess the disadvantage of extensions is that their implementation is seperated from standard classes and looks a little bit odd or difficult to programmers that are not used to them, while their advantage is that they offer a more understandable, tidier and encapsulated use of the language.

于 2014-01-16T12:50:02.273 回答