この質問は時々出てきますが、満足のいく答えを見たことがありません。
典型的なパターンは次のとおりです (行はDataRowです)。
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
私の最初の質問は、どちらがより効率的かということです (私は条件を反転させました):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
これは、 .GetType() の方が高速であることを示していますが、コンパイラは私が知らないいくつかのトリックを知っているのではないでしょうか?
2 番目の質問です。row["value"] の値をキャッシュする価値はありますか、それともコンパイラはインデクサーを最適化しますか?
例えば:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
ノート:
- 行["値"]が存在します。
- 列の列インデックスがわかりません (したがって、列名の検索)。
- DBNullのチェックと割り当てについて具体的に尋ねています(時期尚早の最適化などではありません)。
いくつかのシナリオのベンチマークを行いました (秒単位の時間、10,000,000 回の試行):
row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757
Object.ReferenceEquals は "==" と同じパフォーマンスです
最も興味深い結果は?大文字と小文字を区別して列の名前を一致させない場合 (たとえば、「値」ではなく「値」にすると、(文字列の場合) 約 10 倍の時間がかかります。
row["Value"] == DBNull.Value: 00:00:12.2792374
この話の教訓は、インデックスで列を検索できない場合は、インデクサーに渡す列名が DataColumn の名前と正確に一致していることを確認することです。
値のキャッシュも、ほぼ2 倍高速に表示されます。
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
したがって、最も効率的な方法は次のようです。
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}