Ответ
Duck typing (утиная типизация) — это стиль динамической типизации, при котором объект считается подходящим для использования в определённом контексте, если он реализует все необходимые методы и свойства (имеет нужное "поведение"), а не на основе его явного наследования от конкретного класса или реализации интерфейса. Фраза происходит от идеи: "Если что-то ходит как утка и крякает как утка, то это, вероятно, и есть утка".
В C# утиная типизация реализуется несколькими способами:
-
Ключевое слово
dynamic: Полностью отключает проверку типов на этапе компиляции.public void MakeSound(dynamic animal) { // Проверка наличия метода Quack() произойдет во время выполнения. animal.Quack(); // RuntimeBinderException, если метода нет } // Вызов с любым объектом, имеющим метод Quack(), сработает. MakeSound(new RealDuck()); MakeSound(new ToyDuck()); -
Явные интерфейсы (статическая альтернатива): Предпочтительный способ в C#, когда контракт известен заранее. Это не утиная типизация в чистом виде, но решает ту же задачу — определение по поведению.
public interface ISoundMaker { void MakeSound(); } public class Duck : ISoundMaker { public void MakeSound() => Console.WriteLine("Quack!"); } public class Dog : ISoundMaker { public void MakeSound() => Console.WriteLine("Woof!"); } public void PerformSound(ISoundMaker maker) => maker.MakeSound(); -
Reflection: Позволяет проверить наличие членов объекта программно.
public bool CanQuack(object obj) { var method = obj.GetType().GetMethod("Quack"); return method != null && method.ReturnType == typeof(void) && !method.GetParameters().Any(); }
Плюсы:
- Высокая гибкость и возможность работы с объектами, типы которых не связаны общим предком.
Минусы (для dynamic и Reflection):
- Потеря безопасности типов на этапе компиляции.
- Риск ошибок времени выполнения (
RuntimeBinderException). - Снижение производительности.
- Отсутствие поддержки IntelliSense в IDE.
Вывод: В C# для статического контракта используйте интерфейсы. К dynamic прибегайте только при необходимости, например, при работе с COM, динамическими языками или JSON-объектами с неизвестной структурой.