为什么在实现接口时动态和对象可互换的参数类型?

时间:2018-01-26 01:20:52

标签: c# object dynamic compiler-errors

此问题与objectdynamic之间的一般差异无关,已经得到了解答。以下是针对特定用例的。

假设我有以下界面:

public interface IDoesStuff
{
    void Invoke(dynamic foo1, object foo2);
}

假设我有以下类实现IDoesStuff

public class DoesStuff1 : IDoesStuff
{
    public void Invoke(dynamic foo1, object foo2)
    {
        ...
    }
}

这看起来很正常。但是,我可以为参数交换objectdynamic。例如,以下类将生成编译器错误,导致无法实现IDoesStuff

public class DoesStuff2 : IDoesStuff
{
    public void Invoke(object foo1, dynamic foo2)
    {
        ...
    }
}

因此,实现此界面的类似乎允许我强制参数为object,而是让我使用dynamic。并且以一种方式或另一种方式编写将产生编译器错误,具体取决于我们如何使用参数:

public void Invoke(dynamic foo1, object foo2)
{
    foo1.Bark(); // compiles
}

public void Invoke(object foo1, dynamic foo2)
{
    foo1.Bark(); // does not compile
}

我发现这很奇怪,因为我可能想要传递object并只展示它拥有的几种方法。

我还可以尝试查看是否可以使用dynamic替换另一种类型:

public interface ISomethingElse
{
    void DoWork(int foo)
}

public class SomethingElse : ISomethingElse
{
    public void DoWork(dynamic foo)
    {
        ...
    }
}

不,其他类型会因为没有实现接口而产生编译错误。

那么为什么接口及其实现类之间的dynamicobject可互换参数类型呢?

1 个答案:

答案 0 :(得分:0)

将参数标记为dynamic vs object与C ++中的顶级const相似。它会影响实现方法中的代码,但不会影响调用者。

请注意dynamic根本不属于某种类型。它是语法糖,要求编译器将所有用法转换为DLR调用。因此,强制参数类型匹配将完全没有任何效果。

你提议"也许我确实希望传递一个object并且只暴露它拥有的几种方法"。不可能!

public void DoWork(System.Object foo_param)
{
    dynamic foo = foo_param;
    foo.MethodNotFoundInSystemObject();
    ...
}

由于动态处理是在方法内部进行的,并且无法通过更改方法签名的拼写来防止,因此没有理由实际执行它或甚至将其包含在签名中。

也就是说,如果您使用反射来获取与使用MethodInfo参数类型声明的方法相对应的dynamic,那么您会发现它确实是typeof(System.Object)