Extension methods enable you to "add" methods to existing types without creating a new derived type.
Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.
Sam: When you look at the definition of the extended method, you will see the first parameter to be in the format of "this IMyInterface<T>
In general, you will probably be calling extension methods far more often than implementing your own. A general guideline is that that you implement extension methods sparingly and only when you have to. Use inheritance instead. Sam: so why is Juval Lowy's extension methods (in his book "Programming with WCF") found within "public static class CollectionExtensions" of his ServiceModelEx library a good thing to use?
For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
You can use these methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself. In other words, if a type has a method named Process(int i), and you have an extension method with the same signature, the compiler will always bind to the instance method. When the compiler encounters a method invocation, it first looks for a match in the type's instance methods. If no match is found, it will search for any extension methods that are defined for the type, and bind to the first extension method that it finds.
Some available extension methods
The most common extension methods are LINQ standard query operators that add query functionality to IEnumerable collections and IEnumerable
Example: "OrderBy" extended method on any class that implements IEnumerable<T>
In System.Linq ns, OrderBy is overloaded and defined as
(1) public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
(2) public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey>comparer)
Also in System.Linq, IOrderedEnumerable is defined as
public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable
Using (1), from a client's perspective (where you ignore the 1st param), see how the method takes a delegate Func<Example showing various equivalent ways of calling the "OrderBy" method where its delegate variable parameter points back to a client method.
Assume you have a simple class Pet with 2 public members Name and Age.
Pet[] pets =
{
new Pet { Name="Barley", Age=8 },
new Pet { Name="Boots", Age=4 },
new Pet { Name="Whiskers", Age=1 }
};
//(1a)Explicitly defining the delegate variable Func<TSource, TKey> and pointing it to an explicit method
Func<Pet, int> del = MyFunctionMatchingtheDelegate;
IEnumerable<Pet> query = pets.OrderBy(del);
private static int MyFunctionMatchingtheDelegate(Pet p)
{
return p.Age;
}
//(1b)Implicitly using the delegate variable Func<TSource, TKey> and pointing it to an explicit method
IEnumerable<Pet> query = pets.OrderBy<Pet,int>(MyFunctionMatchingtheDelegate);
//(2a)Explicitly defining the delegate variable Func<TSource, TKey> and pointing it to an anonymous method
Func<Pet, int> del = delegate(Pet p)
{
return p.Age;
};
IEnumerable<Pet> query = pets.OrderBy(del);
//(2b)Implicitly using the delegate variable Func<TSource, TKey> and pointing it to an anonymous method
IEnumerable<Pet> query = pets.OrderBy<Pet, int>
(
delegate(Pet p)
{
return p.Age;
}
);
//(3a)Explicitly defining the delegate variable Func<TSource, TKey> and pointing it to a lambda expression
Func<Pet, int> del = pet => pet.Age;
IEnumerable<Pet> query = pets.OrderBy(del);
//(3b)Implicitly using the delegate variable Func<TSource, TKey> and pointing it to a lambda expression
IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age);
In any case, the actual function (whether lambda expression, anonymous method or explicit method) is not executed until the foreach iterator is first accessed as follows.
foreach (Pet pet in query)
{
Console.WriteLine("{0} - {1}", pet.Name, pet.Age);
}
Notes
In each of the above examples, note we are using the IEnumerable<Pet> iterator even though the definition of OrderBy clearly implies IOrderedEnumerable<Pet>. I'm pretty sure you can use the IOrderedEnumerable in each of the above cases. What are the benefits of using IOrderedEnumerable over IEnumerable, if any?
The other overloaded OrderBy takes an an extra parameter IComparer. Create code examples for that.
Juval Lowy's numerous extension methods apply to IEnumerable<T> and to IEnumerable. Most of his methods also take .NET provided generic delegates like Converter, Action etc. as variables, thus allowing developers to create their own methods the delegates point to.
To Implement Your Own
http://msdn.microsoft.com/en-us/library/bb311042.aspx
(1) It is generally a good idea to extend an interface, not the class.
(2) Understand that if the method you are trying to add already has a matching instance method signature on a class, your extended method will never execute.
[This means, if the type changes and adds a new set of instance methods, one of which matches the extended method you already implemented, then all of a sudden, your extended method will never execute]
(3) Example:
namespace IT.ClientSystems.Extensions
{
using System;
using IT.ClientSystems.Interfaces;
// Define extension methods for any type that implements IMyInterface.
public static class Extension
{
public static void MethodA(this IMyInterface myInterface, int i)
{
Console.WriteLine("Extension.MethodA(this IMyInterface myInterface, int i)");
}
ClientSide: Assume ClassA implements IMyInterface and does not have an instance method called MethodA that takes an integer parameter.
using IT.ClientSystems.Extensions;
ClassA a = new ClassA();
a.MethodA(5);
(4) An advanced example would be for your extended method to take a generic delegate as one of the parameters like "OrderBy" method shown above. Many of System.Linq extension methods and those from Juval's personal library use generic delegate parameters. Common ones are Converter, Action, Predicate, Func etc.
No comments:
Post a Comment