不是所有值类型都可以为空的原因是什么?

时间:2009-07-04 15:16:34

标签: .net nullable

是否有任何惩罚,这样你只应在真正需要它时将它们设置为可空?

由于

5 个答案:

答案 0 :(得分:20)

各种原因:

  • 历史记录:Nullable<T>在.NET 2.0之前不存在,并且无法破坏现有代码 - 尤其是Nullable<T>
  • 的不同装箱规则
  • 含义:如果我想要一个int,我可能想要它可以为空......我希望它是一个int,而我不是想要检查/处理空值
  • 空间:它为每个结构增加了额外的成本...特别是想象一个byte[],现在考虑byte是否可以为空 - 大量的额外开销; *加上它会阻止你做 blits 等* *
  • 效果:Nullable<T>会增加许多额外的惩罚;特别是对.HasValue.Value / .GetValueOrDefault()的大量隐藏调用;这尤其在“提升的运算符”中显示 - 即x + y变为类似于下面的内容,这会增加紧密循环等:

    (x.HasValue && y.HasValue) ? (x.GetValueOrDefault() + y.GetValueOrDefault()) : null

同样,x == y必须检查:

  • 如果两者都为null =&gt;真
  • 如果一个null =&gt;假
  • 否则在每个
  • ==上使用GetValueOrDefault()

很多的开销......

答案 1 :(得分:6)

是的,有罚款。 Nullable<T>结构包含值以及确定值的空值的布尔标志。

虽然布尔值只有一个字节,但结构与偶数字边界对齐。 int使用四个字节的内存,但int?需要八个字节。

答案 2 :(得分:1)

哪些值类型实际上可以为空?我一无所知。

编辑:如果您引用字符串类型,那么它不是值类型,而是引用类型。

答案 3 :(得分:0)

除了Marc Gravell的回答,请查看Nullable&lt; T&gt;的反映代码:

public struct Nullable&lt;T&gt; where T: struct
{
    private bool hasValue;

    internal T value;

    public Nullable(T value)
    {
        this.value = value;
        this.hasValue = true;
    }

    public bool HasValue
    {
        get
        {
            return this.hasValue;
        }
    }
    public T Value
    {
        get
        {
            if (!this.HasValue)
            {
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
            }
            return this.value;
        }
    }
    public T GetValueOrDefault()
    {
        return this.value;
    }

    public T GetValueOrDefault(T defaultValue)
    {
        if (!this.HasValue)
        {
            return defaultValue;
        }
        return this.value;
    }

    public override bool Equals(object other)
    {
        if (!this.HasValue)
        {
            return (other == null);
        }
        if (other == null)
        {
            return false;
        }
        return this.value.Equals(other);
    }

    public override int GetHashCode()
    {
        if (!this.HasValue)
        {
            return 0;
        }
        return this.value.GetHashCode();
    }

    public override string ToString()
    {
        if (!this.HasValue)
        {
            return "";
        }
        return this.value.ToString();
    }

    public static implicit operator T?(T value)
    {
        return new T?(value);
    }

    public static explicit operator T(T? value)
    {
        return value.Value;
    }
}

您会注意到布尔值HasValue的存在以及属性如何使用它。

答案 4 :(得分:0)

考虑实施。 C#中的整数定义为

public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>

结构直接存储在堆栈中,而不是作为指向内存的指针的对象引用(引用本身在堆栈中,但分配在堆栈中)。

NULL引用只是意味着堆栈中的指针尚未初始化为堆中的某个位置。