Подтвердить что ты не робот

Реализация безопасной утиной печати в С#

Посмотрев на то, как Go обрабатывает интерфейсы и любит его, я начал думать о том, как вы могли бы добиться аналогичного утиного набора текста на С# это:

var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);

Метод DuckTyper.Adapt использовал бы System.Reflection.Emit для создания адаптера "на лету". Может, кто-то уже написал что-то подобное. Я предполагаю, что это не слишком отличается от того, что уже издеваются над каркасами.

Однако это приведет к исключению во время выполнения, если Mallard фактически не имеет правильных методов IDuck. Чтобы получить ошибку раньше во время компиляции, мне пришлось бы написать MallardToDuckAdapter, чего я пытаюсь избежать.

Есть ли лучший способ?

edit: по-видимому, правильным термином для того, что я называю "безопасным утиным типом", является структурная типизация.

4b9b3361

Ответ 1

Как вы можете узнать, идет ли корова, как утка и шарлатан, как утка, если у вас нет жизни, дышащая корова перед вами?

Duck-typing - это концепция, используемая во время выполнения. Аналогичная концепция во время компиляции структурная типизация, которая AFAIK не поддерживается CLR. (CLR сосредоточен вокруг именительный набор.)

[Система структурного типа] контрастирует с номинативными системами, где сравнения основаны на явных декларациях или именах типов и утиной печати, в которых только часть структуры, доступная во время выполнения, проверяется на совместимость.

Обычный способ гарантировать, что утиная печать не исключает исключения во время выполнения, - это модульные тесты.

Ответ 2

DuckTyping для С#

Reflection.Emit используется для испускания IL, который напрямую вызывает исходный объект

Я не думаю, что эта библиотека даст вам ошибки времени компиляции, я не уверен, что это будет вполне осуществимо. Используйте Unit Tests, чтобы помочь компенсировать это.

Ответ 3

Я не думаю, что есть другой способ, с помощью которого вы получите ошибку времени компиляции.

Однако это то, что отлично подходит для Unit Testing. Вы должны написать unit test, чтобы убедиться, что

DuckTyper.Adapt<Mallard, IDuck>(mallard);

успешно отображается.

Ответ 4

Я знаю, что неявные интерфейсы (которые являются интерфейсами Go) были запланированы для VB 10 (не знаю о С#). К сожалению, они были отменены до выпуска (я думаю, что они даже не попали в бета-версию...). Было бы неплохо увидеть, появятся ли они в будущей версии .NET.

Конечно, новые типы dynamic могут использоваться для достижения того же уровня, но это все равно не то же самое - неявные интерфейсы по-прежнему допускают сильное типирование, которое я считаю важным.