有没有办法测试变量是否是动态的?

时间:2013-11-05 09:33:39

标签: c# dynamic

除非变量vnull,否则以下代码将始终返回true:

v is dynamic

并且以下测试将无法编译(“typeof运算符不能用于动态类型”):

v.GetType() == typeof(dynamic)

那么有没有办法测试变量是否为dynamic

5 个答案:

答案 0 :(得分:18)

首先,您需要将变量和对象分开。如果变量定义为dynamic ,则变量为动态。就这些。没有更多。 字段属性将使用[Dynamic]属性进行注释,即

public dynamic Foo {get;set;}

实际上是:

[Dynamic]
public object Foo {get;set;}

这基本上可以作为编译器通过dynamic API而不是通过OOP API访问对象的提示。

对象支持完整dynamic功能,如果它实现IDynamicMetaObjectProvider - 但是,可以通过dynamic API和常规访问这样的对象OOP API(它可以兼有)。同样,可以通过任一API访问未实现IDynamicMetaObjectProvider的对象(但是:只有公共成员才能通过dynamic获得)。

答案 1 :(得分:12)

没有名为dynamic的CLR类型。 C#编译器生成类型为dynamic的所有object值,然后调用自定义绑定代码以确定如何处理它们。如果使用dynamic,则会显示为Object

但您可以检查实例是否为IDynamicMetaObjectProvider类型,或者您可以检查类型是否实现IDynamicMetaObjectProvider

答案 2 :(得分:2)

在C#中,动态意味着没有complile-time检查,它将具有=符号另一侧的类型。但是GetType是一个运行时评估,因此您总是要检索声明的类型而不是动态。

您可以在此处阅读更多内容:http://msdn.microsoft.com/en-us/magazine/gg598922.aspx

答案 3 :(得分:0)

总会有其他人说过的运行时类型。

有一个hack来检测局部变量,依赖于动态变量不支持扩展方法这一事实。

static void DummyDynamicTest<T>(this T t) //extension method
{

}

dynamic test = 1;
try
{
    test.DummyDynamicTest();
    //not dynamic
}
catch (RuntimeBinderException)
{
    //dynamic
}

但是,您无法将该功能重构为另一种方法。在任何有意义的场景中,这都不是非常有用,不惜一切代价忽略。

答案 4 :(得分:-1)

@nawfal遗憾的是,当传入任何非动态的普通poco类时,你的扩展方法会失败。

@Marc Gravell建议的解决方案是正确的。我认为混淆在于这样一个事实:尽管你可以宣称任何东西都是动态的。但是,当您将其实例化为具体类时,它不再是真正动态的。以下是我投入的一些测试。只有test2和test3才能通过。您可以尝试设置一些在每个动态上都存在的属性来进一步测试它。这将导致非动态动态异常。 :)

class Program
{
    private class MyDynamic: DynamicObject
    {

    }

    static void Main(string[] args)
    {
        dynamic test1 = new { Name = "Tim" };
        //although I used the dynamic keyword here, it is NOT dynamic. dynamics are only dynamics if they support dynamically adding properties
        //uncommenting this line will cause an exception
        //test.LastName = "Jones"
        if (test1 is IDynamicMetaObjectProvider) { Console.WriteLine("test1"); }

        dynamic test2 = new MyDynamic();
        if (test2 is IDynamicMetaObjectProvider) { Console.WriteLine("test2"); }

        dynamic test3 = new ExpandoObject();
        if (test3 is IDynamicMetaObjectProvider) { Console.WriteLine("test3"); }

        dynamic test4 = new List<string>();
        if (test4 is IDynamicMetaObjectProvider) { Console.WriteLine("test4"); }
    }
}