C# 有没有办法测试一个变量是否是动态的?

C# 有没有办法测试一个变量是否是动态的?,c#,dynamic,C#,Dynamic,除非变量v为null,否则以下代码将始终返回true: v is dynamic 并且以下测试将不会编译(“typeof运算符不能用于动态类型”): 那么,有没有一种方法可以测试变量是否是动态的?没有称为动态的CLR类型。C#编译器生成类型为object的所有动态值,然后调用自定义绑定代码以确定如何处理它们。如果使用了动态,它将显示为对象 但是您可以检查实例的类型是否为IDynamicMetaObjectProvider,或者您可以检查该类型是否实现了IDynamicMetaObjectPro

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

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


那么,有没有一种方法可以测试变量是否是动态的?

没有称为动态的CLR类型。C#编译器生成类型为
object
的所有
动态
值,然后调用自定义绑定代码以确定如何处理它们。如果使用了
动态
,它将显示为
对象


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

首先,您需要将变量和对象分开。如果变量定义为动态变量,则该变量为动态变量。仅此而已。没有别的了。字段或属性将使用
[Dynamic]
属性进行注释,即

public dynamic Foo {get;set;}
实际上是:

[Dynamic]
public object Foo {get;set;}
这基本上是作为编译器通过
dynamic
API而不是通过oopapi访问对象的提示

如果对象实现了
IDynamicMetaObjectProvider
,则它支持完整的
dynamic
功能-但是,这样的对象可以通过
dynamic
API和常规OOP API访问(它可以同时具有这两种功能)。同样,一个没有实现
IDynamicMetaObjectProvider
的对象可以通过任一API访问(但是:只有公共成员可以通过
dynamic
)。

在C#dynamic中意味着没有complile时间检查,它将具有=符号另一侧的类型。然而,GetType是一个运行时计算,所以您总是要检索声明的类型,而不是动态的


您可以在这里阅读更多内容:

正如其他人所说,总会有一个运行时类型

基于动态变量不支持扩展方法这一事实,存在一种检测局部变量的方法

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

}

dynamic test = 1;
try
{
    test.DummyDynamicTest();
    //not dynamic
}
catch (RuntimeBinderException)
{
    //dynamic
}
staticvoiddummydynamictest(thistt)//扩展方法
{
}
动态试验=1;
尝试
{
test.dummy dynamictest();
//非动态
}
捕获(RuntimeBinderException)
{
//动态的
}

但是,您不能将功能重构为其他方法。这在任何有意义的场景中都不是很有用,不管付出什么代价都可以忽略

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

@Marc Gravell提出的解决方案是正确的。我认为困惑在于这样一个事实,即即使你可以声明任何东西都是动态的。然而,当您将它实例化为一个具体的类时,它就不再是真正的动态的。以下是我对它的一些测试。只有test2和test3应该通过。您可以通过尝试设置每个动态上不存在的属性来进一步测试它。这将导致非动态动力学异常。:)

类程序
{
私有类MyDynamic:DynamicObject
{
}
静态void Main(字符串[]参数)
{
动态test1=new{Name=“Tim”};
//虽然我在这里使用了dynamic关键字,但它不是动态的。只有当动态关键字支持动态添加属性时,它才是动态的
//取消对此行的注释将导致异常
//test.LastName=“琼斯”
if(test1是IDynamicMetaObjectProvider){Console.WriteLine(“test1”);}
动态测试2=新的MyDynamic();
if(test2是IDynamicMetaObjectProvider){Console.WriteLine(“test2”);}
动态测试3=新的ExpandooObject();
if(test3是IDynamicMetaObjectProvider){Console.WriteLine(“test3”);}
动态测试4=新列表();
if(test4是IDynamicMetaObjectProvider){Console.WriteLine(“test4”);}
}
}

实例决不是“类型
IDynamicMetaObjectProvider
”,因为它不是具体类型。当然,类型可以实现这一点(这句话的后半部分很好)。@MarcGravell,从多态性的角度来看,实现IFoo的类Foo是一个IFoo。可能我的英语不太好。这里有一个例子:
typeof(IDynamicMetaObjectProvider)。IsAssignableFrom(typeof(ExpandoObject))
当然检查
测试是不是IDynamicMetaObjectProvider
更简单、更有效、更正确?@nawful这是什么情况?具体的例子?(真诚地感兴趣)@MarcGravel同样如此<代码>动态测试=1。现在
测试是IDynamicMetaObjectProvider返回false。啊,我明白了——我们说的是两码事:你说的纯粹是变量;我说的是价值。当涉及到变量时,它是由变量声明100%定义的——我不确定“测试”已定义的局部变量类型实际上有多有用,因为它就在定义中。更简单的“测试”是:看看定义。这有点像询问是否
字符串x
是一个
int
。。。嗯,不是-它是一个
字符串
。您不需要为此进行测试。@MarcGravel OP在变量声明之后。我同意,在我使用的上下文中,它一点用处都没有。你所说的动态价值是什么意思?我没有得到那个角色。换句话说,在哪种情况下,
IDynamicMetaObjectProvider
会派上用场?(真正感兴趣)对于那些拥有较长微软经验的人来说,
dynamic
是新的
IDispatch
。仔细想想你是否想处理它。相关:@nawfal有趣的问题!遗憾的是,对于这种问题,目前还没有现成的方法——也许下一版本的DRL中会有这种方法。@dav_i您试图检测的动态是什么?你能给我们举个例子说明变量
v
是如何声明和使用的吗?或者浏览我答案的评论部分,你可能会得到更好的答案
static void DummyDynamicTest<T>(this T t) //extension method
{

}

dynamic test = 1;
try
{
    test.DummyDynamicTest();
    //not dynamic
}
catch (RuntimeBinderException)
{
    //dynamic
}
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"); }
    }
}