除非变量v
为null
,否则以下代码将始终返回true:
v is dynamic
并且以下测试将无法编译(“typeof运算符不能用于动态类型”):
v.GetType() == typeof(dynamic)
那么有没有办法测试变量是否为dynamic
?
答案 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"); }
}
}