Why use C#extension methods?

Asked

Viewed 1,698 times

27

What I get with extension methods I don’t earn with inheritance?

Simply using it as the same name is complicated, since it creates more confusion than anything else.

  • Explain the second sentence better.

  • Like I use String a million times and I know everything about her, but then she has some different method than expected...

  • I explain this in my reply, but I will improve on this point.

4 answers

20


There is a question that partially answers what is being asked here: Java 8 "default method" versus C# "extend method". I will not repeat here what is already there.

Extension method has nothing to do with inheritance. In fact the inheritance use is abused and should be avoided whenever possible.

Extension methods do not add behavior to a class. They are unrelated utility methods, which work primarily with a type of data. It is only a syntactic sugar in static methods out of class and there is no inheritance relation. Therefore have disadvantages cited in the question linked above.

All modern languages are providing better extensibility mechanisms than inheritance after realizing that the latter does not deliver the wonders they preached in the beginning. Inheritance is still useful where polymorphism is needed and reuse also.

  • Gain more fluent syntax than static methods, which even helps the IDE help you.
  • Gains the reduction of functionality coupling. It reduces the need to use design patterns to get this kind of advantage (ok, this can be achieved only with static methods, but so is more convenient). Inheritance is one of the worst types of coupling.
  • Gain the possibility to add features precisely without making inheritance. Several types can even be inherited (structs, classes sealed, record and enum - example). Inheritance would be inadequate in others. So it’s used more to add functionality to something that already exists and you don’t have or don’t want to have control.
  • Allows linking methods to interfaces. This is very powerful, especially if you consider that it is usually better program for interfaces. Increase reuse (since version 8 has even more interesting ways).
  • Lets choose (depending on how it was written) at the time of use whether it will be available for your code or not. For example, if you do not add the System.Linq in its code, LINQ methods do not pollute the possibilities of using methods.
  • He is the basis of LINQ. Without extension methods it would be extremely complex and there would be a lot of incompatibility create it (see Java). That’s a huge gain.

Confusion of extra method names

One of the things that one should avoid is not putting the static class(s) extension method(s) into it namespace which type he is extending. This will make the extension method always available to that type. Sure, it might be useful to do that, but only do it if you’re sure it’ll be advantageous.

If you just want the extension method to be available when you choose, just create in a namespace separately and then only with its import (with using) that the method will be available.

For example avoid creating a:

namespace System {
    public static class ObjectExt {
        pubic static bool IsNull(this object source) => source == null;
    }
}

I put in the Github for future reference.

This will make all objects of all types available, always!

Every resource can be abused. Do not abuse this.

If you take something that’s abused and gets in your way, consider changing your "supplier".

Completion

Remember that access to the object in an extension method does not have access privileges to non-public members. What can be even a good one in most cases. But it can bring some difficulty in others.

There are controversies whether inheritance or extension methods should be used as standard when both are possible.

Examples of use:

Interfacing:

static Random r = new Random(DateTime.Now.Millisecond);
public static void Shuffle<T>(this IList<T> list, int lowerItem, int upperItem) {
    upperItem = upperItem > list.Count ? list.Count : upperItem;
    lowerItem = lowerItem < 0 ? 0 : lowerItem;
    for (int i = lowerItem; i < upperItem; i++) {
        int j = r.Next(i, upperItem);
        T tmp = list[j];
        list[j] = list[i];
        list[i] = tmp;
    }
}

I put in the Github for future reference.

Site with several useful methods, some abused.

  • I just didn’t understand the (syntactic sugar), but the part of the LINQ leaves it well that is very well using the way it is.

  • I already found the Here

  • In fact I saw some advantage now, some advantages seem the same of composition over inheritance... One thing I read there that made me curious "Gain the possibility of linking methods to interfaces" Is that true? Like an interface with the implementation of a method? Sorry I used Java and some things are still weird in C#

  • @diegocolli yes, it’s true, but it’s not as good as what you can do in Java. read the first link on the differences between languages at this point. At least today. Languages evolve. Java had nothing, C# plans a more powerful feature yet.

  • What do you think of the idea of simulating "mixins" with Extensions Methods, @bigown? I read an old article about this idea, which I can’t find, but I found the idea interesting. Of course, the use of the word "mixin" is not the most appropriate, but the idea itself I found good.

  • 1

    To explain better, an example post, which is not very good, but serves to exemplify: http://www.codeproject.com/Articles/27930/Understanding-Extension-Methods-and-Mixin And this gist I built based on the idea. https://gist.github.com/gtkatakura/60c8de78274588a049cabc66a6ffb16b

  • Although it is not the idea of a "Mixin", since we do not have linearization here and [maybe? ] we don’t even have a "state", the idea looks more like a "Trait". Except we don’t have an explicit conflict resolution, so it also doesn’t fall under the concept of "traits".

  • @Gabrielkatakura ie is neither mixin, nor trait. There is a proposal to add trait in C#, but will only do when they are sure they will do it right.

  • The example used to ObjectExt would not work because if the object is null would result in a NullReferenceException. But overall I liked the answer.

  • Yes, actually the idea is far from being a Mixin, she’s closer to a Trait. In my opinion, it seems something even closer to the Java Defaults Methods.

  • @Richarddias you are mistaken, you are not accessing any member, so it would not generate error.

  • @Gabrielkatakura but also is not, see the first link of response.

  • @bigown, imagining the use of the following form: var obj = PegarPorId('IDInexistenteParaRetornarNull'); obj.IsNull(); //Null reference exception. It wouldn’t be like this?

  • No, because it’s syntactic sugar for System.ObjectExt.IsNull(obj) :) The method is not part of the truth object, the object does not need to exist to invoke the extension method.

Show 9 more comments

13

Extension methods allow you to add a method to a class without creating a new derivative type, some classes cannot be inherited as the String class and the values types (Structs).

You might want to count how many words there are in a string and for that

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}

and to use

using ExtensionMethods;

string s = "Hello Extension Methods";
int i = s.WordCount();             // com extension
int j = MyExtensions.WordCount(s); // sem extension
  • Okay I didn’t know I couldn’t inherit from some classes in C#

  • @diegocolli The classes "marked" with the modifier Sealed cannot be inherited. See here as the String class is declared.

5

One point I haven’t seen anyone address, and a bit more technical, is a type of code-bloating that consumes more memory than desirable.

The more a class has defined members, the greater the amount of metadata stored in memory that is required to represent the existence of the type. These metadata are required regardless of whether to use reflection or not, at least in part, because of the Garbage Collector. This in turn uses the information of object types to be able to navigate the object graph and be able to clear those that are not referenced by any other object, so it needs to know the memory layout of each type.

Increasing the amount of metadata is not necessarily bad, but a problem arises in the use of Generics. A generic type like List<T> that over the years has come gaining more and more members, is that whenever a new type List<T1>... List<Tn> is defined, a new portion of memory is allocated to store metadata of that type, as each instance of object points to its metadata. Each time the generic type increases, this increase is multiplied by all the different specific uses of the generic type, and so you start using a lot of memory only with metadata.

The Xtension methods have come in good time to end the need to expand these types so that they all remain very stable since this feature was introduced.

3

Let’s go to something very practical, for an understanding without complication!

You have to do a certain operation on an object type several times, for example, clear a string and leave only the numbers, right!

Instead of building a class with a method, and calling this to the object that needs the treatment, you create an extension of this type, which will be available on this object always throughout your system!

public static string OnlyNumbers(this string str)
{
    List<char> numbers = new List<char>("0123456789");
    StringBuilder toReturn = new StringBuilder(str.Length);
    CharEnumerator enumerator = str.GetEnumerator();

    while (enumerator.MoveNext())
    {
        if (numbers.Contains(enumerator.Current))
            toReturn.Append(enumerator.Current);
    }
    return toReturn.ToString();
}

In this case we return the new value of this string where only numbers!

The thing is, certain action is done repeatedly for a type of object, so it’s more practical to create an extended method of that kind!

Applying

string telefone = telefonePosted.OnlyNumbers();
  • Only supplemented, which will be available in this object always throughout your system! .... only where the class references the class that contains the method.

  • @Marconciliosouza to be available throughout your system, just use the same Namespace for the extension class/method as the base class! ;) (Of course in all your system, once you reference the base type, the extension will be available)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.