首页 > 解决方案 > mscorlib 的 `System.Boolean` 如何避免结构布局循环?

问题描述

参考源网站上的源代码System.Boolean指出,实例struct Boolean仅包含一个bool字段private bool m_value::

https://referencesource.microsoft.com/#mscorlib/system/boolean.cs,f1b135ff6c380b37

namespace System {

    using System;
    using System.Globalization;
    using System.Diagnostics.Contracts;

    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public struct Boolean : IComparable, IConvertible
#if GENERICS_WORK
        , IComparable<Boolean>,  IEquatable<Boolean>
#endif
    {
      private bool m_value;

      internal const int True = 1; 
      internal const int False = 0; 

      internal const String TrueLiteral  = "True";
      internal const String FalseLiteral = "False";

      public static readonly String TrueString  = TrueLiteral;
      public static readonly String FalseString = FalseLiteral;
}

但我注意到...

那么这段代码是如何编译的呢?

标签: c#

解决方案


简短回答:这是一种特殊情况,与类型装箱及其底层表示有关。这些类型对于编译器来说是众所周知的,因此与常规类型相比,运行时的核心部分和编译器/JIT 优化器对这些类型的处理略有不同。


由于这深埋在运行时实现中,我认为语言规范不会涉及特定的运行时实现细节。我不确定这是否是一个足够令人满意的答案,但我认为在这种特殊情况下,该bool类型仍然是未装箱的,因此作为结构的一部分作为原始值类型存在。

值类型的装箱和拆箱的语义是故意不透明的,以使使用该语言更容易。在这种情况下,Boolean结构本身似乎依赖于实现特定的装箱规则来实现实际的语义,例如:

  // Determines whether two Boolean objects are equal.
  public override bool Equals (Object obj) {
    //If it's not a boolean, we're definitely not equal
    if (!(obj is Boolean)) {
      return false;
    }

    return (m_value==((Boolean)obj).m_value);
  }

我相信在上面,表示布尔类型的盒装结构首先进行类型检查,然后将其拆箱并bool直接比较内部值。与装箱类型(可能是标记指针或具有一些运行时类型信息的实际结构)不同,未装箱类型被视为实际数据。

我在内部相信,如果必须将 bool 装箱以传递为System.Object(因为类型擦除或无法进行优化),您最终会得到类似于 this 的true内容1

ldc.i4.1
box        [mscorlib]System.Boolean

因此,虽然在较高级别上bool看起来System.Boolean是相同的并且可以类似地进行优化,但在运行时的这种特殊情况下,盒装和非盒装版本之间的区别bool直接暴露出来。类似地,bool无法将未装箱的类型与System.Object固有的装箱类型进行比较。就解释原理本身而言,有关装箱/拆箱需求的答案更加深入。

在托管语言中,当涉及到一些核心运行时特性时,运行时实现通常需要免除某些规则,这对于 Java 和其他基于 JVM 的语言来说当然是正确的。虽然我也不熟悉 CLR,但我认为这里也适用相同的原则。

虽然这个关于 'bool' 是 'System.Boolean' 的类型别名的问题基本上涵盖了一般用例,但当接近运行时实现时,C# 的方言变得更像“特定于实现的 C#”,这可能会稍微改变规则.


推荐阅读