【问题标题】:How does the compiler recognise Nullable<T> to be a 'special type'?编译器如何将 Nullable<T> 识别为“特殊类型”?
【发布时间】:2014-02-14 10:36:59
【问题描述】:

Nullable&lt;T&gt; 是一个具有以下定义的结构:

public struct Nullable<T> where T : struct

其中struct 是一个类型约束,因此 T 被约束(根据规范 §4.4.4):

  • 结构类型或枚举类型
  • 不是可以为空的类型。

在源代码中查找Nullable&lt;T&gt; 没有特殊属性(除了[Serializable]),那么编译器如何将其识别为“可空类型”?

针对以下cmets:

intInt32别名

(§4.1.4) 简单类型通过保留字标识,但这些 保留字只是 aliases 中预定义的结构类型 系统命名空间

T?Nullable&lt;T&gt;简写

(§4.1.10) - 可空类型写为 T?,其中 T 是底层 类型。此语法是 System.Nullable 的简写,两者 表格可以互换使用。

这似乎是一个明显的区别,下面没有反映出来。

那么编译器如何将一个简单的结构(没有特殊代码)识别为“可空类型”,结构名称?

【问题讨论】:

  • 嗯,这是一种特殊的类型;这也是编译器理解“int?”的原因。作为“可空”。
  • 您可能会发现this answer 很有帮助
  • @ken2k - 我不同意,这只是一个类型别名,所以编译器会在编译期间简单地将int? 转换为Nullable&lt;int&gt;
  • C# 编译器当然对 Nullables 有深入的了解。例如,它允许他们使用 ??运算符并允许对它们进行提升的转换运算符。目前还不清楚您要问的是什么特定方面。
  • @Selman22 - 我同意这个问题更多地是关于“特殊类型”的。 Eric 对Are all of these special cases hard coded into the compiler? Yes. 的回复可能回答了这个问题。

标签: c# .net generics clr nullable


【解决方案1】:

基于Shared Source CLI 2.0Nullable&lt;T&gt; 通过PREDEFTYPEDEF 宏变得“特殊”,该宏采用名称“System.Nullable”并将其映射到属性PT_G_OPTIONAL,该属性在其余部分进行检查编译器。

关于intSystem.Int32等的别名,见“好名字”一栏。

来自sscli20\csharp\inc\predeftype.h

//         id            full type name       required  simple     numer    AggKind  fund type   elementtype,      nice name,    zero, quasi simple numer, attribute arg size serialization type,  predef attribute, arity, in mscorlib)
PREDEFTYPEDEF(PT_BYTE,   "System.Byte",         1,            1,      1,     Struct,   FT_U1,   ELEMENT_TYPE_U1,      L"byte",      0,                 0,      1,      SERIALIZATION_TYPE_U1,      PA_COUNT, 0, 1)
PREDEFTYPEDEF(PT_SHORT,  "System.Int16",        1,            1,      1,     Struct,   FT_I2,   ELEMENT_TYPE_I2,      L"short",     0,                 0,      2,      SERIALIZATION_TYPE_I2,      PA_COUNT, 0, 1)
PREDEFTYPEDEF(PT_INT,    "System.Int32",        1,            1,      1,     Struct,   FT_I4,   ELEMENT_TYPE_I4,      L"int",       0,                 0,      4,      SERIALIZATION_TYPE_I4,      PA_COUNT, 0, 1)
PREDEFTYPEDEF(PT_LONG,   "System.Int64",        1,            1,      1,     Struct,   FT_I8,   ELEMENT_TYPE_I8,      L"long",      &longZero,         0,      8,      SERIALIZATION_TYPE_I8,      PA_COUNT, 0, 1)
// ... snip ...
// Nullable<T>
PREDEFTYPEDEF(PT_G_OPTIONAL, "System.Nullable",  0,     0,     0,   Struct,   FT_STRUCT,  ELEMENT_TYPE_END,      NULL,          0,                 0,      0,      0,                          PA_COUNT, 1, 1)

然后它在其他地方像这样使用:

来自sscli20\csharp\sccomp\nullable.cpp

/***************************************************************************************************
    Return true iff the method is the nullable ctor taking one parameter.
***************************************************************************************************/
bool FUNCBREC::IsNubCtor(METHSYM * meth)
{
    return meth && meth->getClass()->isPredefAgg(PT_G_OPTIONAL) && meth->params->size == 1 &&
        meth->params->Item(0)->isTYVARSYM() && meth->isCtor();
}

对于阅读此问题的读者,您可能是Shared Source CLI 2.0 Internals 的目标受众,该书以免费电子书形式发布。

【讨论】:

  • 哇!惊人的答案。所以简短的回答确实是硬编码的结构名称是什么将System.Nullable 标识为特殊的?
猜你喜欢
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 2013-10-25
  • 1970-01-01
  • 2020-06-30
  • 2023-03-11
相关资源
最近更新 更多