【问题标题】:How is Nullable<T> different from a similar custom C# struct?Nullable<T> 与类似的自定义 C# 结构有何不同?
【发布时间】:2012-12-08 10:52:33
【问题描述】:

Nullable micro-optimizations, part one 中,Eric 提到Nullable&lt;T&gt; 有一个奇怪的装箱行为,这是类似的用户定义类型无法实现的。

C# 语言赋予预定义的Nullable&lt;T&gt; 类型有哪些特殊功能?尤其是那些不能在 MyNullable 类型上工作的。

当然,Nullable&lt;T&gt; 有特殊的语法糖 T?,但我的问题更多是关于语义的。

【问题讨论】:

  • 我在这里发现您的问题纯属偶然。考虑在博客帖子本身上留下这样的问题。另外,如果您对发布有任何疑问,请随时给我发电子邮件;在博客的“关于”页面上有联系信息。
  • 我确实考虑过,但我也想了解更多关于拳击以外的特殊支持,所以我求助于 Stack Overflow。

标签: c# nullable language-features boxing


【解决方案1】:

我的意思是:不存在盒装可空对象。当您装箱 int 时,您会得到对装箱 int 的引用。当您将int? 装箱时,您将获得空引用或对装箱int 的引用。你永远不会得到一个盒装的int?

您可以轻松地创建自己的 Optional&lt;T&gt; 结构,但您无法实现具有这种装箱行为的结构。 Nullable&lt;T&gt; 的特殊行为已融入运行时。

这个事实导致了一些奇怪的事情。例如:

仅供参考,Nullable&lt;T&gt; 类型还有其他“神奇”的方式。例如,虽然它是一个结构类型,但它不满足结构约束。您无法创建具有该属性的自己的结构。

【讨论】:

  • 我明白了......所以如果我理解正确,优化是这些奇怪行为的原因。谢谢你的解释!
  • @EldritchConundrum:不是这样。相反,这些奇怪之处是可空值语义和可空引用语义之间不匹配的结果。这个故事的寓意是:在 v1.0 中为类型系统添加可空性,而不是 v2.0。如果同时发明可空引用类型和可空值类型,它们会更加相似。
  • @EricLippert:你认为事情会有什么不同?我对Nullable&lt;T&gt; 设计的最大反对意见是——至少根据我的理解——在大多数情况下,当代码获得Nullable&lt;T&gt; 时,它想要的是T,并指出它是否有效; Nullable&lt;T&gt; 周围的许多额外内容阻碍了该基本任务。你有不同的看法吗?
【解决方案2】:

我在C# specifications找到了这两个:

  • is 运算符适用于 T?,就像它适用于 T 一样,as 运算符可以转换为可为空的类型。
  • 对不可为空的值类型进行操作的预定义和用户定义的运算符被提升为这些类型的可空形式。

现在,以下是我认为仅限于Nullable&lt;T&gt;的功能:

  • switch 中的值可以是可为空的类型。我不认为这很重要,因为 switch 还接受可以在 MyNullable 类型上定义的用户定义的隐式转换。
  • 支持可空的 IDisposable 类型,在生成的 Dispose() 调用之前插入空检查。我不认为这很重要,因为我可以将 MyNullable 定义为一个类,然后它会是一样的。

以下是我不确定的:

  • 规范中提到了装箱/拆箱和隐式/显式转换,但我不明白是否可以使用 MyNullable 实现相同的结果。

【讨论】:

  • 没有办法指定除Nullable以外的值类型不应该转换为Object,或者这样的转换结果不应该是具有相同字段的对象struct,初始化为相同的值。
【解决方案3】:

C# 提升了可空类型的运算符。例如:

int? SumNullableInts(int? a, int? b)
{
    return a + b;
}

您必须在 MyNullable&lt;T&gt; 中进行大量反射工作才能支持这一点,然后以下内容将编译,它不应该:

MyNullable<List<string>.Enumerator> SumNullableEnumerators(MyNullable<List<string>.Enumerator> a, MyNullable<List<string>.Enumerator> b)
{
    return a + b;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多