Làm thế nào để `System.Boolean` của mscorlib tránh các chu kỳ bố trí cấu trúc?


10

Mã nguồn cho System.Booleantại trang web Nguồn tham chiếu cho biết các phiên bản của struct Booleanchỉ chứa một booltrường duy nhất 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;
}

Nhưng tôi nhận thấy rằng ...

  • boollà một bí danh ngôn ngữ C # cho System.Boolean.
  • Loại là loại struct Booleangiá trị có nghĩa là nó không thể chứa chính nó như là một trường .
  • ... nhưng mã này có lẽ sẽ biên dịch.
  • Tôi hiểu rằng khi -nostdliblựa chọn trình biên dịch được thiết lập bạn cần cung cấp riêng của bạn quan trọng định nghĩa kiểu như System.String, System.Int32, System.Exception- đó là sự khác biệt duy.
  • Mã nguồn được xuất bản không chứa các thuộc tính đặc biệt khác như [MethodImpl( MethodImplOptions.InternalCall )].

Vậy làm thế nào để mã này biên dịch?


1
Đó là một minh chứng rõ ràng rằng giả định phổ biến "nó là bí danh" là một mô hình tinh thần bị phá vỡ. boollà một từ khóa trong ngôn ngữ C #. Cả trình biên dịch và thời gian chạy đều có nhiều kiến ​​thức tích hợp về loại và không cần trợ giúp từ System.Boolean. Các khai báo trong mscorlib cho các loại giá trị nguyên thủy khớp với biểu diễn đóng hộp của loại.
— Hans Passant

Câu trả lời:


3

Câu trả lời ngắn : Đó là một trường hợp đặc biệt, liên quan đến loại quyền anh và đại diện cơ bản của họ. Các loại này nổi tiếng với trình biên dịch và do đó được xử lý hơi khác nhau bởi các phần cốt lõi của thời gian chạy và trình tối ưu hóa trình biên dịch / JIT so với các loại thông thường.


Vì điều này được chôn sâu trong quá trình thực thi thời gian chạy, tôi cho rằng đặc tả ngôn ngữ sẽ không đi vào chi tiết thực hiện thời gian chạy cụ thể. Tôi không chắc đây có phải là một câu trả lời đủ thỏa đáng hay không nhưng tôi nghĩ trong trường hợp cụ thể này, boolloại vẫn không được đóng hộp và do đó tồn tại dưới dạng một loại giá trị thô như là một phần của cấu trúc.

Các ngữ nghĩa của quyền anh và unboxing các loại giá trị là cố ý mờ để làm cho việc sử dụng ngôn ngữ dễ dàng hơn. Trong trường hợp này, Booleancấu trúc dường như dựa vào các quy tắc đấm bốc cụ thể để thực hiện các ngữ nghĩa thực tế như:

  // 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);
  }

Tôi tin ở trên, một cấu trúc hình hộp đại diện cho kiểu boolean được kiểm tra kiểu đầu tiên, sau đó nó được bỏ hộp và boolgiá trị bên trong được so sánh trực tiếp. Không giống như một loại được đóng hộp, có thể là một con trỏ được gắn thẻ hoặc một cấu trúc thực tế với một số thông tin loại thời gian chạy, các loại không có hộp được coi là dữ liệu thực tế.

Tôi tin rằng trong nội bộ, nếu một bool phải được đóng hộp để bị loại bỏ System.Object(vì loại bỏ hoặc không thể tối ưu hóa), bạn sẽ kết thúc với một cái gì đó dọc theo dòng này cho truehộp giá trị 1.

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

Vì vậy, ở mức độ cao boolvà có System.Booleanvẻ giống hệt nhau và có thể được tối ưu hóa tương tự, trong trường hợp cụ thể này trong thời gian chạy, sự khác biệt giữa các phiên bản đóng hộp và không có hộp boolđược phơi bày trực tiếp. Similary, một hộp boolkhông có hộp có thể được so sánh với System.Objectloại vốn là một loại hộp. Câu trả lời này liên quan đến sự cần thiết của quyền anh / unboxing đi sâu hơn rất nhiều khi giải thích nguyên tắc này.

Trong các ngôn ngữ được quản lý, việc triển khai thời gian chạy thường cần được miễn trừ khỏi một số quy tắc nhất định khi nói đến một số tính năng thời gian chạy cốt lõi, điều này chắc chắn đúng với Java và các ngôn ngữ dựa trên JVM khác. Mặc dù tôi không quen thuộc với CLR, tôi sẽ nghĩ rằng nguyên tắc tương tự được áp dụng ở đây.

Trong khi câu hỏi này về 'bool' là bí danh loại cho 'System.Boolean' về cơ bản bao gồm các trường hợp sử dụng chung, khi đến gần với triển khai thời gian chạy, phương ngữ của C # trở nên giống như "C # cụ thể thực hiện", có thể uốn cong các quy tắc một chút .


Tôi đánh giá cao điều này vì cái nhìn sâu sắc của bạn - nhưng tôi không thể đánh dấu đây là câu trả lời được chấp nhận vì nó không có thẩm quyền, xin lỗi :(
— Dai
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.