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"); }
}
}