Les méthodes d'extension de C# 3: réponse au quizz
Réponse au post: https://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:
- plusieurs méthodes d'extensions peuvent étendre un même type.
- plusieurs méthodes d'extensions peuvent étendre des types appartenant à la même hiérarchie de classes
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.
- Si plusieurs solutions sont trouvées pour un même type alors une erreur de compilation est soulevée.
- Si plusieurs solutions sont trouvées pour différents types dans la même hiérarchie (classes ou interfaces) alors c'est le type de la référence qui compte et non celui de l'instance !!!
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
Comments
Anonymous
July 25, 2007
Le fait de pouvoir rajouter des extension methods sur des interfaces est aussi un moyen de faire du <u>pseudo</u> héritage multiple (avec les problèmes de conflits dont parle Mitsu qui vont avec).Anonymous
July 26, 2007
Comment faire une methode d'extention pour un objet et non pour l'instance d'un objet ?Anonymous
July 26, 2007
Si tu parles d'ajouter une méthode statique par extension, ça n'est pas possible. Les méthodes d'extension portent forcément sur des instances.Anonymous
August 19, 2007
quelles sont les similitudes et les différences avec les méthodes amies de c++Anonymous
October 05, 2007
Aucun rapport à mon sens.