Реализация безопасной утки в C # - PullRequest
17 голосов
/ 13 ноября 2009

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

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 : по-видимому, правильный термин для того, что я называю «безопасной уткой», - это структурная печать .

Ответы [ 4 ]

13 голосов
/ 13 ноября 2009

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

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

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

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

5 голосов
/ 13 ноября 2009

DuckTyping для C #

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

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

1 голос
/ 13 ноября 2009

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

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

1 голос
/ 13 ноября 2009

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

Тем не менее, это то, для чего отлично подходит Unit Testing. Вы бы написали модульный тест, чтобы убедиться, что

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

успешно карт.

...