11

是否有任何惩罚,以便您仅在真正需要时才将它们设置为可为空的?

谢谢

4

5 回答 5

20

很多原因:

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

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

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

  • 如果两者都为 null => true
  • 如果一个 null => false
  • 否则==使用GetValueOrDefault()每个

很多开销....

于 2009-07-04T15:33:53.240 回答
6

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

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

于 2009-07-04T15:21:52.640 回答
1

哪些值类型实际上可以为空?我一个都不知道。

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

于 2009-07-04T15:20:36.230 回答
0

除了 Marc Gravell 的回答,检查 Nullable<T> 中的反射代码:

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以及属性如何使用它。

于 2009-07-04T17:01:17.007 回答
0

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

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

结构体直接存储在堆栈中,与作为内存指针的对象引用相反(引用本身在堆栈中,但分配在堆栈中)。

NULL 引用仅仅意味着堆栈中的指针尚未初始化到堆中的位置。

于 2009-07-29T20:18:09.713 回答