En los lenguajes funcionales (como lisp), utiliza la coincidencia de patrones para determinar qué sucede con un elemento en particular en una lista. El equivalente en C # sería una cadena de sentencias if ... elseif que verifican el tipo de un elemento y realizan una operación basada en eso. No hace falta decir que la comparación de patrones funcionales es más eficiente que la verificación de tipos en tiempo de ejecución.
Usar polimorfismo sería una coincidencia más cercana a la coincidencia de patrones. Es decir, hacer que los objetos de una lista coincidan con una interfaz particular y llamar a una función en esa interfaz para cada objeto. Otra alternativa sería proporcionar una serie de métodos sobrecargados que toman un tipo de objeto específico como parámetro. El método predeterminado que toma Objeto como su parámetro.
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
}
}
Este enfoque proporciona una aproximación a la coincidencia de patrones Lisp. El patrón de visitantes (como se implementó aquí, es un gran ejemplo de uso para listas heterogéneas). Otro ejemplo sería para el envío de mensajes en el que hay escuchas para ciertos mensajes en una cola de prioridad y mediante el uso de la cadena de responsabilidad, el distribuidor pasa el mensaje y el primer controlador que coincide con el mensaje lo maneja.
La otra cara es notificar a todas las personas que se registran para recibir un mensaje (por ejemplo, el patrón de agregador de eventos que se usa comúnmente para el acoplamiento suelto de modelos de vista en el patrón MVVM). Yo uso el siguiente constructo
IDictionary<Type, List<Object>>
La única forma de agregar al diccionario es una función
Register<T>(Action<T> handler)
(y el objeto es en realidad una WeakReference a la que se pasa en el controlador). Así que aquí TENGO que usar List < Object > porque en el momento de la compilación, no sé cuál será el tipo cerrado. Sin embargo, en Runtime puedo hacer cumplir que ese tipo será la clave para el diccionario. Cuando quiero disparar el evento que llamo
Send<T>(T message)
y de nuevo resuelvo la lista. No hay ninguna ventaja al usar List < dynamic > Porque necesito lanzarlo de todos modos. Entonces, como ven, hay méritos para ambos enfoques Si va a enviar dinámicamente un objeto utilizando la sobrecarga de métodos, dinámico es la forma de hacerlo. Si está FORZADO a emitir independientemente, también puede usar Objeto.