【问题标题】:Why can't a Type be used as a constant value?为什么不能将 Type 用作常量值?
【发布时间】:2015-11-19 16:16:04
【问题描述】:

引用MSDN - const (C# reference):

常量表达式是可以在编译时完全计算的表达式。因此,引用类型常量的唯一可能值是 stringnull 引用。

根据:typeof(T) vs. Object.GetType() performancetypeof(T) 是编译时表达式。

那么为什么Type 不能是一个常量值呢?

以下代码不会编译:

public const Type INT_TYPE = typeof(int);

【问题讨论】:

  • 不知道是什么让你问这个问题,你肯定不会在实际代码中使用这样的常量吗?
  • 为此我使用静态只读来代替。

标签: c# .net types reference constants


【解决方案1】:

TypeTypeInfo 对象的运行时引用。直到运行时才知道该 TypeInfo 对象将驻留的位置。

【讨论】:

    【解决方案2】:

    C# 编译器和 IL 肯定支持将类型作为常量表达式,至少在某些情况下是这样。看看属性,他们经常使用这个:

    [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
    

    该类型作为字符串嵌入在编译器生成的代码中,上面的行编译为以下 IL 代码:

    .custom instance void System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class System.Type) = (
        01 00 39 53 79 73 74 65 6d 2e 43 6f 6c 6c 65 63
        74 69 6f 6e 73 2e 47 65 6e 65 72 69 63 2e 4d 73
        63 6f 72 6c 69 62 5f 43 6f 6c 6c 65 63 74 69 6f
        6e 44 65 62 75 67 56 69 65 77 60 31 00 00
    )
    

    如果您检查二进制数据,您会注意到这是完全限定的类名,没有任何程序集标识 (System.Collections.Generic.Mscorlib_CollectionDebugView`1)。

    回答您的问题:我看不出有任何技术原因导致这不可能,我也无法想象兼容性考虑会阻止它,因为没有序列化程序集引用,因此声明此类型的 DLL 仍然可以在没有的情况下更新影响之前编译的引用它的类型。

    【讨论】:

      【解决方案3】:

      来自MSDN

      常量可以是数字、布尔值、字符串或空引用。

      常量基本上仅限于可以在编译类型表示为二进制值的原始值(因为它在编译时被“注入”到客户端代码中)。由于Type 是一个具有多个属性的,因此没有一个简单的二进制表示可以“烘焙”到客户端代码中。

      【讨论】:

        【解决方案4】:

        编译器用生成的 IL 代码中的文字值替换常量。但是typeof是一个方法调用:

        typeof(int);
        
        // Becomes:
        L_0000: ldtoken int32
        L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        

        【讨论】:

          【解决方案5】:
          public const Type INT_TYPE = typeof(int);
          

          上述代码无法编译的原因正是 MSDN 所述的确切原因——在编译应用程序时无法确定常量的值。使用 typeof(int) 需要在 runtime 确定常量的值。理论上,.NET 可以允许上面的语句编译,但它不会是严格意义上的常量。

          【讨论】:

          • 为什么在编译时不知道typeof(int)
          • 因为你可以为AnyCPUtypeof(int) 编译代码在不同的架构上会有所不同。 Type 是一个类型的运行时reference,而不是编译时常量。
          • @jwdonahue,不正确。 docs.microsoft.com/en-us/previous-versions/visualstudio/… 。只有指针和引用类型的大小会发生变化,这可能取决于正在运行的框架(32 位还是 64 位)。
          • @MattChambers typeof(int) != sizeof(int)typeof(int) 返回的 Type 的实际值可能因系统而异。我想不出为什么它不会在同一个盒子上从一个运行时更改为另一个运行时。 Type 用于类型的特定实例是在运行时派生的,而不是在编译时派生的。
          • 好吧,如果大小没有不同,为什么 typeof 结果需要不同? IE。为什么不恒定?
          猜你喜欢
          • 2019-03-07
          • 2016-08-16
          • 1970-01-01
          • 2015-01-21
          • 2014-01-06
          • 1970-01-01
          • 2023-01-22
          相关资源
          最近更新 更多