C#混淆隐式类型变量与动态

C#混淆隐式类型变量与动态,c#,dynamic,implicit-typing,C#,Dynamic,Implicit Typing,如果运行TestClass.Test(),将获得RuntimeBinderException。这一切都始于var str=DoSomething(obj)隐式键入动态而不是字符串。有人能解释一下这里发生了什么吗?为什么需要字符串(str)工作?我知道你不能在动态对象上调用扩展方法,但这整件事让我觉得有点肮脏和破碎。尽管存在明显的类型不匹配,但它仍然可以正常编译,然后在运行时失败 public static class ExtensionTest { public static strin

如果运行TestClass.Test(),将获得RuntimeBinderException。这一切都始于
var str=DoSomething(obj)隐式键入动态而不是字符串。有人能解释一下这里发生了什么吗?为什么
需要字符串(str)工作?我知道你不能在动态对象上调用扩展方法,但这整件事让我觉得有点肮脏和破碎。尽管存在明显的类型不匹配,但它仍然可以正常编译,然后在运行时失败

public static class ExtensionTest
{
    public static string ToJsonTest(this object x)
    {
        return string.Empty;
    }
}
public static class TestClass
{
    public static void Test()
    {
        dynamic obj = new ExpandoObject();
        obj.var1 = "hello";

        var str = DoSomething(obj);
        var testObj = RequiresString(str);
        var json = testObj.ToJsonTest();
    }
    public static string DoSomething(object x)
    {
        return string.Empty;
    }
    public static TestObj RequiresString(string x)
    {
        return new TestObj();
    }
    public class TestObj
    {
        public int Prop1 { get; set; }
    }
}

requireString
的调用包含
dynamic
参数,因此它在运行时使用实际参数的类型进行解析。
DoSomething
返回的实际类型是
string
,因此运行时绑定器查找
requirestring(string)
,可以成功找到
TestClass.requirestring
。到目前为止,一切顺利

正如您已经提到的,下一次调用
testObj.ToJsonTest()
失败,因为
dynamic
上的扩展方法是目标,所以下一次调用失败


是的,它可能感觉有点脏,因为当涉及
dynamic
s时,(几乎)没有编译时检查,非常像弱类型脚本语言。这就是为什么我建议只在真正需要的情况下,在尽可能狭窄的范围内使用
dynamic
;特别是,我要说的是,不应该在类的公共表面上看到
动态

它是脏的&我不确定这是否完全回答了你的问题,但这里有一个讨论扩展方法在CLR中如何工作以及为什么它们不与DLR一起工作的简介:对任何其他人来说,都要明确修改“str”的声明上面的显式类型解决了这个问题,即:
string str=DoSomething(obj)。以防万一有人得出结论,动态是无用的——在这种情况下,不要使用“var”声明变量。让我困惑的是,为什么DoSomething()返回字符串实际上可以解释为返回动态。没有。它接受一个对象并返回一个字符串。但是由于某种原因,返回类型发生了变化。只定义了一个DoSomething(),它返回一个字符串,而不是动态字符串。仅仅将一个动态对象传递给一个函数,该函数期望一个对象以某种方式神奇而有效地改变函数的返回类型。是否正在编译某些DoSomething`1()?这对我来说仍然是胡说八道。@jeromeyers:好吧,总是有可能有多个重载具有不同的返回类型。在这种情况下,我们无法预测实际类型,因此必须是动态的。如果结果的类型取决于重载的数量,那就很奇怪了。顺便说一句,这个调用可能会返回一个更具体的类型,因此动态调用它可能会导致在下一个调用中选择其他重载。@jeromeyers:Eric Lippert有一篇关于这个的好文章:很好的文章-正是需要的。非常感谢。