有没有办法测试变量是否是动态的?
除非变量v
为null
否则以下代码将始终返回true:
v is dynamic
并且以下测试将无法编译(“typeof运算符不能用于动态类型”):
v.GetType() == typeof(dynamic)
那么有没有办法测试变量是否是dynamic
?
首先,您需要将变量和对象分开。 如果变量定义为dynamic
变量,则该变量是dynamic
。 就这些。 没有更多。 字段或属性将使用[Dynamic]
属性进行注释,即
public dynamic Foo {get;set;}
实际上是:
[Dynamic] public object Foo {get;set;}
这基本上作为编译器通过dynamic
API而不是通过OOP API访问对象的提示。
如果一个对象实现了IDynamicMetaObjectProvider
,它就支持完整的dynamic
function – 但是,这样的对象可以通过dynamic
API和常规OOP API(它可以同时具有)来访问。 同样,可以通过任一API访问未实现IDynamicMetaObjectProvider
的对象(但是:只有公共成员才能通过dynamic
)。
没有称为dynamic
CLR类型。 C#编译器生成类型为object
所有dynamic
值,然后调用自定义绑定代码以确定如何处理它们。 如果使用dynamic
,它将显示为Object
。
但您可以检查实例是否为IDynamicMetaObjectProvider
类型,或者您可以检查该类型是否实现IDynamicMetaObjectProvider
在C#中,动态意味着没有complile-time检查,它将具有=符号的另一侧的类型。 但是GetType是运行时评估,因此您总是要检索声明的类型而不是动态。
你可以在这里阅读更多内容: http : //msdn.microsoft.com/en-us/magazine/gg598922.aspx
总有一种运行时类型,正如其他人所说的那样。
有一个hack来检测局部变量,依赖于动态变量不支持扩展方法的事实。
static void DummyDynamicTest(this T t) //extension method { } dynamic test = 1; try { test.DummyDynamicTest(); //not dynamic } catch (RuntimeBinderException) { //dynamic }
但是,您无法将该function重构为另一种方法。 在任何有意义的场景中,这都不是非常有用,不惜任何代价忽略。
@nawfal遗憾的是,当传入任何非动态的普通poco类时,你的扩展方法会失败。
@Marc Gravell提出的解决方案是正确的。 我认为混淆在于即使你可以宣布任何动态的事实。 但是,当您将其实例化为具体类时,它不再是真正动态的。 以下是我投入的一些测试。 只有test2和test3才能通过。 您可以通过尝试设置每个动态上不存在的属性来进一步测试它。 这将导致非动态动态exception。 🙂
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(); if (test4 is IDynamicMetaObjectProvider) { Console.WriteLine("test4"); } } }