这是最近的一个案例,其中使用dynamic 是一个简单的解决方案。
我已将一些代码从 VB6 移植到 C#。移植后的代码仍然需要通过 COM 互操作调用 VB6 对象上的其他方法。
需要调用的类如下所示:
class A
{
void Foo() {...}
}
class B
{
void Foo() {...}
}
(即,这将是 VB6 类通过 COM 互操作在 C# 中查看的方式;特别是自动生成的 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();
}
这会将类型安全性推迟到运行时,但假设您已正确完成它就可以正常工作。
我不会为新代码背书,但在这种情况下(从这里的其他答案来看,我认为这并不少见)它很有价值。
考虑的替代方案:
注意:这可能只是一个临时解决方案。最终,如果移植剩余的 VB6 代码,则可以使用适当的类结构,静态编译时检查将取代 dynamic 的使用。我承认,如此充满希望的未来让我更愿意使用这种可能存在维护风险的方法。