Dans les langages fonctionnels (comme lisp), vous utilisez la correspondance de modèles pour déterminer ce qui arrive à un élément particulier dans une liste. L'équivalent en C # serait une chaîne d'instructions if ... elseif qui vérifient le type d'un élément et effectuent une opération basée sur cela. Il va sans dire que la mise en correspondance de modèles fonctionnels est plus efficace que la vérification du type d'exécution.
L'utilisation du polymorphisme serait une correspondance plus étroite avec la correspondance de motifs. C'est-à-dire que les objets d'une liste correspondent à une interface particulière et appellent une fonction sur cette interface pour chaque objet. Une autre alternative serait de fournir une série de méthodes surchargées qui prennent un type d'objet spécifique comme paramètre. La méthode par défaut prenant Object comme paramètre.
public class ListVisitor
{
public void DoSomething(IEnumerable<dynamic> list)
{
foreach(dynamic obj in list)
{
DoSomething(obj);
}
}
public void DoSomething(SomeClass obj)
{
//do something with SomeClass
}
public void DoSomething(AnotherClass obj)
{
//do something with AnotherClass
}
public void DoSomething(Object obj)
{
//do something with everything els
}
}
Cette approche fournit une approximation de la correspondance de motifs Lisp. Le modèle de visiteur (tel qu'implémenté ici, est un excellent exemple d'utilisation de listes hétérogènes). Un autre exemple serait pour la répartition des messages où, il y a des écouteurs pour certains messages dans une file d'attente prioritaire et en utilisant la chaîne de responsabilité, le répartiteur transmet le message et le premier gestionnaire qui correspond au message le gère.
Le revers est d'avertir tous ceux qui s'inscrivent pour un message (par exemple, le modèle d'agrégateur d'événements couramment utilisé pour le couplage lâche des ViewModels dans le modèle MVVM). J'utilise la construction suivante
IDictionary<Type, List<Object>>
La seule façon d'ajouter au dictionnaire est une fonction
Register<T>(Action<T> handler)
(et l'objet est en fait une référence faible au gestionnaire passé dans). Donc, ici, je dois utiliser List <Object> car au moment de la compilation, je ne sais pas quel sera le type fermé. Au Runtime cependant, je peux imposer que ce sera ce type qui sera la clé du dictionnaire. Quand je veux déclencher l'événement que j'appelle
Send<T>(T message)
et encore je résous la liste. Il n'y a aucun avantage à utiliser List <dynamic> car je dois quand même le caster. Donc, comme vous le voyez, il y a des avantages aux deux approches. Si vous allez distribuer dynamiquement un objet à l'aide de la surcharge de méthode, dynamique est le moyen de le faire. Si vous êtes forcé de lancer quoi que ce soit, vous pourriez aussi bien utiliser Object.