Réponse au post: http://blogs.msdn.com/mitsufu/archive/2007/07/23/geek-quizz.aspx
Alors, alors..., le code étrange de la méthode d'extension .AsEnumerable(), bien que paraissant inutile à la première lecture sert bien à quelque chose.
Le point technique très propre aux méthodes d'extension est le suivant:
Une méthode d'extension étend les fonctionnalités d'une classe depuis "l'extérieur". Etant juste une simplification d'écriture, cette technique ne casse pas les règles objets.
Ainsi, ces méthodes sont forcément publiques et n'accèdent qu'à la visibilité publique de l'objet qu'elles étendent.
La syntaxe de la méthode statique:
MyExtensions.AsEnumerable(obj);
se simplifie tout simplement en:
obj.AsEnumerable();
On remarque cependant que MyExtensions n'apparait pas dans la seconde syntaxe. AsEnumerable doit donc être déterminé par le compilateur. Comment s'y prendre ?
Plusieurs questions en découlent:
Première conclusion, il peut y avoir des conflits !
En effet, les méthodes d'extensions sont recherchées par le compilateur dans la portée courante.
Ainsi, si l'on implémente deux méthodes d'extensions identiques sur deux types héritant l'un de l'autre:
public class A { } public class B : A { } public static class MyExtensions { //Etend la classe A public static void Test(this A a) { ... } public static void Test(this B b) { ... } }
B b = new B();b.Test();
appelle la méthode qui étend B
A a = b;a.Test();
appelle la méthode qui étend A, alors que l'instance est bien de type B.
Pour conclure, nous avons le même pattern avec les interfaces IEnumerable<T> et IQueryable<T>. Quasiment toutes les fonctionnalités de Linq (where, orderby, select, count, etc) étendent ces deux interfaces.
La méthode .AsEnumerable(), en ne faisant que renvoyer une référence typée en IEnumerable<T> depuis n'importe quelle object implémentant cette interface permet de forcer l'appelle des méthodes d'extension de ce type.
Mitsu