【问题标题】:how are nullable types implemented under the hood in .net?如何在.net 中实现可空类型?
【发布时间】:2011-01-31 00:30:44
【问题描述】:

在我们自己的 Jon Skeet 的 C# in depth 中,他讨论了为值类型模拟“null”的 3 种方法:

  • 魔术值(例如,最早可能的 DateTime 被视为“null”)
  • 引用类型包装器
  • 布尔标志

提到可空类型使用第三种方法。可空类型到底是如何工作的?

【问题讨论】:

  • 无耻插件:我不久前写了一篇关于它如何工作的博客文章:softwareblog.alcedo.com/post/2010/02/16/…
  • @FredrikMörk 链接不再可用...
  • @M.Mimpen 现在又可以使用了。那个博客前一阵子让我崩溃了,但我已经在其他地方重新发布了,但是对原始网址进行了重定向。

标签: c# .net nullable


【解决方案1】:

最终,它们只是一个带有 bool 标志的通用结构——除了特殊的装箱规则。因为结构(默认情况下)初始化为零,所以 bool 默认为 false(无值):

public struct Nullable<T> where T : struct {
    private readonly T value;
    private readonly bool hasValue;
    public Nullable(T value) {
        this.value = value;
        hasValue = true;
    }
    public T Value {
        get {
           if(!hasValue) throw some exception ;-p
           return value;
        }
    }
    public T GetValueOrDefault() { return value; }
    public bool HasValue {get {return hasValue;}}
    public static explicit operator T(Nullable<T> value) {
        return value.Value; }
    public static implicit operator Nullable<T>(T value) {
        return new Nullable<T>(value); }
}

不过还有额外的区别:

  • 特殊的拳击规则(你通常不能这样做)
  • 用于比较 null 等的特殊 C# 规则
  • “提升”C# 中的运算符(在 .NET 中通过 EqualityComparer&lt;T&gt;Comparer&lt;T&gt; 等)
  • 关于泛型类型约束的特殊规则(防止Nullable&lt;Nullable&lt;T&gt;&gt;

【讨论】:

  • 拳击是如何处理的?我可以为自己的结构实现自己的装箱规则吗?
  • 它由 CLI 中的特殊规则处理。不,您不能自己这样做。同样,“提升”的运营商也不是你可以自己做的。
  • 另外值得注意的是,运算符的行为是由语言控制的——C#和VB对不同的运算符有不同的规则。
  • 我只是遇到了一个不同:你可以给T?方法参数一个默认值T,但是如果你实现你自己的可空值并尝试做同样的事情,你会得到编译错误。 (例如,“'bool' 类型的值不能用作默认参数,因为没有标准转换为 'MyNullable' 类型”。)这是否属于您的要点之一?
【解决方案2】:

Nullable&lt;T&gt; 通过提供两个字段来工作:

private bool hasValue;
internal T value;

属性从这些中起作用。如果设置为null,则hasValue设置为false。

【讨论】:

  • 但这并不简单,因为TNullable&lt;T&gt;都是结构体,结构体不能轻易设置为null
猜你喜欢
  • 1970-01-01
  • 2010-11-23
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 2012-02-28
相关资源
最近更新 更多