Ugrás a tartalomhoz

.NET Programming Technologies

Gergely Kovásznai, Csaba Biró

Eszterházy Károly College

Extension Methods

Extension Methods

In the previous section, we created a simple, but universal method (FilterDates) to filter given dates. As it can be expected, in .NET there are already existing solutions for such basic tasks such as filtering. When browsing the methods of the List class, one can spot the Where method, which performs exactly this kind of filtering, and can be used instead of our own FilterDates method:

IEnumerable<DateTime> datesToDisplay = dates.Where(d => d.Year > 2000);

When browsing the methods of dates (as a List), one can notice that it has a bunch of useful methods that are similar to Where, e.g., for searching, sorting, filtering, summing etc. One can also discover that those methods do not actually belong to the List class, but rather to the IEnumerable interface. However, in reality, IEnumerable defines one single method (GetEnumerator). Where do those useful methods come from, and where are they defined? Well, programmers have developed them outside of IEnumerable, inside other classes, and then – so to speak – they extended IEnumerable with those external methods.

Before getting to know existing extension methods other than Where, let us see in a nutshell how to write extension methods by ourselves! First, we need to create a public and static class, since extension methods are only allowed to be defined in such classes. The first parameter of an extension method must begin with the this keyword. The type of this first parameter specifies the type (class or interface) that is about to be extended with the given method. In the example below, the string class gets extended with a method that counts all the occurrences of a given character in a string.

public static class MyExtensionMethods

{

        public static int CountChar(this string s, char c)

        {

                int count = 0;

                foreach (char x in s)

                        if (x == c) count++;

                return count;

        }

        ...

}

You can check that any string object has, from now on, a CountChar method, and you can call it! E.g., "almafa".CountChar('a')

In another example, let us extend List<string> objects with a method that converts all their elements to uppercase:

public static List<string> ToUpper(this List<string> stringList)

{

        List<string> newList = new List<string>();

        foreach (string s in stringList)

                newList.Add(s.ToUpper());

        return newList;

}

As mentioned before, we can use a large repertoire of already existing extension methods. We have already seen the Where and OrderBy methods, which extend the IEnumerable interface, but besides those two, there exist a lot of other extension methods that are useful in queries. Note that you need to import the System.Linq namespace (by using the using keyword) in order to use those extension methods in your source code! The reason for that is that those extension methods are defined in the Enumerable (static) class in the System.Linq namespace, according to exactly the same rules that we have introduced above.[9] In Section Hiba! A hivatkozási forrás nem található., we are going to give a detailed survey on the most important such extension methods, but first, let us introduce another way of using those methods, namely a special declarative syntax.



[9] For instance, the signature of the System.Linq.Enumerable.Where method:

public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate);

As can be seen, the this keyword is standing before the first parameter, therefore this method extends the IEnumerable<T> interface. The type of the second parameter is a delegate (defined in the System namespace), which expects a parameter of arbitrary type (T) and returns bool.