En 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 instrucciones if ... elseif que verifican el tipo de un elemento y realizan una operación basada en eso. No es necesario decir que la coincidencia de patrones funcionales es más eficiente que la verificación del tipo de tiempo de ejecución.
El uso del 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 Object 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 visitante (como se implementa aquí, es un gran ejemplo de uso para listas heterogéneas). Otro ejemplo sería para el envío de mensajes, donde hay escuchas para ciertos mensajes en una cola de prioridad y utilizando una cadena de responsabilidad, el despachador pasa el mensaje y el primer controlador que coincide con el mensaje lo maneja.
El otro lado está notificando a todos los que se registran para un mensaje (por ejemplo, el patrón de Agregador de eventos comúnmente utilizado para el acoplamiento suelto de ViewModels 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 al controlador pasado). 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 asegurar que será ese tipo la clave del diccionario. Cuando quiero disparar el evento llamo
Send<T>(T message)
y nuevamente resuelvo la lista. No hay ninguna ventaja en usar List <dynamic> porque necesito lanzarlo de todos modos. Como ve, hay ventajas en ambos enfoques. Si va a despachar dinámicamente un objeto utilizando la sobrecarga de métodos, la forma dinámica es hacerlo dinámico. Si estás FORZADO a lanzar independientemente, también podrías usar Object.