是否有任何惩罚,以便您仅在真正需要时才将它们设置为可为空的?
谢谢
很多原因:
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
必须检查:
==
使用GetValueOrDefault()
每个很多开销....
是的,有罚款。该Nullable<T>
结构包含该值以及一个确定该值是否为空的布尔标志。
尽管布尔值只有一个字节,但结构与偶数字边界对齐。Anint
使用四个字节的内存,但 anint?
需要八个字节。
哪些值类型实际上可以为空?我一个都不知道。
编辑:如果您引用字符串类型,那么它不是值类型,而是引用类型。
除了 Marc Gravell 的回答,检查 Nullable<T> 中的反射代码:
public struct Nullable<T> 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
以及属性如何使用它。
考虑实施。C# 中的整数定义为
public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>
结构体直接存储在堆栈中,与作为内存指针的对象引用相反(引用本身在堆栈中,但分配在堆栈中)。
NULL 引用仅仅意味着堆栈中的指针尚未初始化到堆中的位置。