Вот недавний случай, когда использование dynamic
было простым решением.
Я перенес некоторый код из VB6 в C #. Этот перенесенный код все еще был необходим для вызова других методов на объектах VB6 через COM-взаимодействие.
Классы, которые нужно вызвать, выглядели так:
class A
{
void Foo() {...}
}
class B
{
void Foo() {...}
}
(то есть, именно так классы VB6 выглядят в C # через COM-взаимодействие; в частности, COM-вызываемая оболочка, которая была автоматически сгенерирована).
Поскольку A и B не зависят друг от друга, вы не можете привести их друг к другу, и у них нет общего базового класса (COM не поддерживает то, что AFAIK и VB6 определенно не поддерживают. И они не реализовали общий интерфейс - см. ниже).
Исходный код VB6, который был перенесен, сделал это:
' Obj must be either an A or a B
Sub Bar(Obj As Object)
Call Obj.Foo()
End Sub
Теперь в VB6 вы можете передавать вещи как Object
, и среда выполнения выяснит, есть ли у этих объектов метод Foo()
или нет. Но в C # буквальный перевод будет:
// Obj must be either an A or a B
void Bar(object Obj)
{
Obj.Foo();
}
Что НЕ будет работать. Он не скомпилируется, потому что object
не имеет метода с именем "Foo", и C #, будучи безопасным с точки зрения типов, этого не допустит.
Таким образом, простым «исправлением» было использование dynamic
, например:
// Obj must be either an A or a B
void Bar(dynamic Obj)
{
Obj.Foo();
}
Это откладывает безопасность типов до времени выполнения, но при условии, что вы все сделали правильно, работает просто отлично.
Я бы не одобрил это для нового кода, но в этой ситуации (которая, я думаю, нередко судят по другим ответам здесь) это было ценно.
Рассмотрены альтернативы:
Использование отражения для вызова Foo (). Вероятно, будет работать, но больше усилий и меньше читабельности.
Модификации библиотеки VB6 здесь не было, но, возможно, мог бы быть подход для определения A и B с точки зрения общего интерфейса, который поддерживали бы VB6 и COM. Но использовать динамику было намного проще.
Примечание. Возможно, это временное решение. В конце концов, если оставшийся код VB6 будет перенесен, тогда можно будет использовать правильную структуру класса, и статическая проверка времени компиляции заменит использование dynamic
. Я признаю, что такое обнадеживающее будущее сделало меня более удобным при использовании этого подхода, который может иметь некоторый риск обслуживания.