本当に必要な場合にのみnull許容として設定する必要があるなどのペナルティはありますか?
ありがとう
様々な理由:
Nullable<T>
.NET 2.0まで存在せず、既存のコードを壊すことはできません-特にNullable<T>
int
ないかもしれません...私はそれをにしたいと思います、そして私はnullをチェック/処理する必要はありませんint
byte[]
かどうかを検討してください-多くの余分なオーバーヘッド。*それに加えて、それはあなたがブリットなどbyte
をするのを止めるでしょう*パフォーマンス:Nullable<T>
多くの追加のペナルティが追加されます。特に、.HasValue
および.Value
/への隠された呼び出しがたくさんあり.GetValueOrDefault()
ます。これは、特に「持ち上げられた演算子」で示されます。つまりx + y
、以下のようになり、タイトなループなどが追加されます。
(x.HasValue && y.HasValue) ? (x.GetValueOrDefault() + y.GetValueOrDefault()) : null
同様に、x == y
以下を確認する必要があります。
==
しますGetValueOrDefault()
たくさんのオーバーヘッド...
はい、ペナルティがあります。構造には、値と、値のNullable<T>
nullを決定するブールフラグが含まれています。
ブール値は1バイトだけですが、構造体は単語の境界に均等に配置されます。は4バイトのint
メモリを使用しますが、int?
8バイトが必要です。
どの値型が実際にnull許容ですか?私は誰も知りません。
編集:文字列型を参照する場合、それは値型ではなく、参照型です。
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参照は、スタック内のポインターがヒープ内の場所に初期化されていないことを意味します。