この質問はときどき出てきますが、満足のいく答えは見当たりません。
典型的なパターンは(行は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"])) {}
ノート:
- 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();
}
IDataRecord
拡張機能を気に入っていただろう。