У функціональних мовах (наприклад, lisp) ви використовуєте відповідність шаблону, щоб визначити, що відбувається з певним елементом у списку. Еквівалент у C # буде ланцюжком, якщо ... elseif висловлювання, які перевіряють тип елемента і виконують на основі цього операцію. Потрібно сказати, що функціональна відповідність шаблону є більш ефективною, ніж перевірка типу виконання.
Використання поліморфізму було б ближче до відповідності зразком. Тобто, наявні об'єкти списку відповідають певному інтерфейсу і викликають функцію в цьому інтерфейсі для кожного об’єкта. Іншою альтернативою було б надання серії перевантажених методів, які приймають конкретний тип об'єкта як параметр. Метод за замовчуванням, який приймає Object як його параметр.
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
}
}
Цей підхід забезпечує наближення до відповідності шаблону Lisp. Шаблон відвідувачів (як реалізований тут, є чудовим прикладом використання для гетерогенних списків). Іншим прикладом може бути відправлення повідомлень, де в черзі пріоритету є слухачі певних повідомлень, і, використовуючи ланцюг відповідальності, диспетчер передає повідомлення та обробляє перший обробник, який відповідає повідомленню.
Зворотна сторона сповіщає всіх, хто зареєструється для повідомлення (наприклад, шаблон агрегатора подій, який зазвичай використовується для вільного з'єднання ViewModels у шаблоні MVVM). Я використовую наступну конструкцію
IDictionary<Type, List<Object>>
Єдиний спосіб додати до словника - це функція
Register<T>(Action<T> handler)
(а об'єкт насправді є слабким посиланням на передане обробник). Тому тут я маю використовувати List <Object>, оскільки під час компіляції я не знаю, що буде закритим типом. Однак під час виконання програми я можу стверджувати, що саме цей тип є ключовим для словника. Коли я хочу запустити подію, яку я дзвоню
Send<T>(T message)
і знову вирішую список. Немає переваги у використанні List <dynamic>, тому що мені все одно потрібно його передати. Отже, як ви бачите, є достоїнства обох підходів. Якщо ви збираєтесь динамічно відправляти об'єкт, використовуючи метод перевантаження, динамічний спосіб це зробити. Якщо ви змушені брати участь незалежно, ви можете також використовувати Object.