Nei linguaggi funzionali (come lisp), si utilizza la corrispondenza dei modelli per determinare cosa succede a un particolare elemento in un elenco. L'equivalente in C # sarebbe una catena di istruzioni if ... elseif che controllano il tipo di un elemento ed eseguono un'operazione basata su quello. Inutile dire che la corrispondenza del modello funzionale è più efficiente della verifica del tipo di runtime.
L'uso del polimorfismo sarebbe una corrispondenza più stretta con la corrispondenza dei modelli. Cioè, avere gli oggetti di un elenco corrisponde a un'interfaccia particolare e chiamare una funzione su quell'interfaccia per ciascun oggetto. Un'altra alternativa sarebbe quella di fornire una serie di metodi sovraccarichi che prendono come parametro uno specifico tipo di oggetto. Il metodo predefinito che accetta Object come parametro.
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
}
}
Questo approccio fornisce un'approssimazione della corrispondenza del modello di Lisp. Il modello di visitatore (come implementato qui, è un ottimo esempio di utilizzo per elenchi eterogenei). Un altro esempio potrebbe essere l'invio di messaggi in cui, ci sono listener per determinati messaggi in una coda prioritaria e usando una catena di responsabilità, il dispatcher passa il messaggio e il primo gestore che corrisponde al messaggio lo gestisce.
Il rovescio della medaglia sta notificando a tutti coloro che si registrano per un messaggio (ad esempio il pattern Aggregator di eventi comunemente usato per l'accoppiamento libero di ViewModels nel pattern MVVM). Uso il seguente costrutto
IDictionary<Type, List<Object>>
L'unico modo per aggiungere al dizionario è una funzione
Register<T>(Action<T> handler)
(e l'oggetto è in realtà un WeakReference per il gestore passato). Quindi qui DEVO usare List <Object> perché in fase di compilazione, non so quale sarà il tipo chiuso. In Runtime, tuttavia, posso far valere che sarà quel Tipo a essere la chiave del dizionario. Quando voglio lanciare l'evento che chiamo
Send<T>(T message)
e di nuovo risolvo l'elenco. Non c'è alcun vantaggio nell'usare Elenco <dinamico> perché devo comunque lanciarlo. Quindi, come vedi, ci sono dei meriti per entrambi gli approcci. Se hai intenzione di inviare un oggetto in modo dinamico usando l'overload del metodo, dinamico è il modo per farlo. Se sei FORZATO a lanciare indipendentemente, potresti anche usare Object.