【问题标题】:Is there a way to test if a variable is dynamic?有没有办法测试变量是否是动态的?
【发布时间】:2021-10-17 11:19:18
【问题描述】:

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

v is dynamic

并且下面的测试将无法编译(“The typeof operator cannot be used on the dynamic type”):

v.GetType() == typeof(dynamic)

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

【问题讨论】:

  • 对于那些拥有较长 Microsoft 经验的人,dynamic 是新的IDispatch。认真考虑是否要处理它。
  • @nawfal 有趣的问题!很遗憾,对于这类问题,没有现成的方法存在——也许在下一个版本的 DRL 中会出现。
  • @dav_i 您要检测的动态是什么?你能举个例子告诉我们变量v是如何声明和使用的吗?或者通过我的答案的评论部分,你可能会得到更好的主意..
  • @nawfal 实际上我遇到的问题是您链接到的问题,但我的问题更笼统。正如马克在您的评论链中所说 - 有时 OP(我)不知道他们在问什么。仍然 - 我觉得在这么多人回答之后改变问题是违反 SO 方式的。

标签: c# dynamic


【解决方案1】:

首先,您需要将变量和对象分开。一个变量是动态的如果它被定义为dynamic。就这些。没有什么了。 fieldproperty 将使用[Dynamic] 属性进行注释,即

public dynamic Foo {get;set;}

其实是:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 实例从不IDynamicMetaObjectProvider”类型,因为它不是具体类型。当然,类型可以实现(那句话的后半部分很好)。
    • @MarcGravell,从多态性的角度来看,类 Foo 实现了 IFoo IS-A IFoo。可能我的英语不完美。
    • 这里是一个例子:typeof(IDynamicMetaObjectProvider).IsAssignableFrom(typeof(ExpandoObject))
    【解决方案3】:

    在 C# 中,动态意味着没有编译时检查,它将具有 = 符号另一侧的类型。然而 GetType 是一个运行时评估,所以你总是会检索声明的类型而不是动态的。

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

    【讨论】:

      【解决方案4】:

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

      根据动态变量不支持扩展方法这一事实,可以检测局部变量。

      static void DummyDynamicTest<T>(this T t) //extension method
      {
      
      }
      
      dynamic test = 1;
      try
      {
          test.DummyDynamicTest();
          //not dynamic
      }
      catch (RuntimeBinderException)
      {
          //dynamic
      }
      

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

      【讨论】:

      • 肯定检查test is IDynamicMetaObjectProvider 更简单、更高效、更正确?
      • @nawful 那是什么情况?具体例子? (真正感兴趣)
      • @MarcGravell 一样。 dynamic test = 1;。现在test is IDynamicMetaObjectProvider; 返回 false。
      • 啊,我明白了 - 我们在谈论不同的目的:您纯粹是在谈论 变量;我说的是。当涉及到 variable 时,它 100% 由变量声明定义 - 我不确定“测试”局部变量的定义类型实际上有多大用处,因为那是 就在定义中。更简单的“测试”是:查看定义。这有点像问string x; 是否是int...嗯,no - 它是string。您不需要为此进行测试。
      • @MarcGravell OP 在变量声明之后。我同意它在我使用的上下文中根本没有用。 value 是动态的是什么意思?我没有得到那部分。换句话说,IDynamicMetaObjectProvider 在什么情况下会派上用场? (真正感兴趣)
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多