Cette question revient de temps en temps, mais je n'ai pas vu de réponse satisfaisante.
Un modèle typique est (la ligne est un DataRow ) :
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Ma première question est de savoir lequel est le plus efficace (j'ai inversé la condition) :
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Ce site indique que .GetType() devrait être plus rapide, mais peut-être le compilateur connaît-il quelques astuces que je ne connais pas ?
Deuxième question, cela vaut-il la peine de mettre en cache la valeur de row["value"] ou le compilateur optimise-t-il l'indexeur de toute façon ?
Par exemple :
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Notes :
- row["value"] existe.
- Je ne connais pas l'index de la colonne (d'où la recherche par nom de colonne).
- Ma question porte spécifiquement sur la vérification de l'absence de DBNull, puis sur l'affectation (et non sur l'optimisation prématurée, etc.).
J'ai évalué quelques scénarios (temps en secondes, 10.000.000 d'essais) :
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 a les mêmes performances que "==".
Le résultat le plus intéressant ? Si le nom de la colonne ne correspond pas à la casse (par exemple, "Value" au lieu de "value"), il faut environ dix fois plus de temps (pour une chaîne de caractères) :
row["Value"] == DBNull.Value: 00:00:12.2792374
La morale de l'histoire semble être que si vous ne pouvez pas rechercher une colonne par son index, assurez-vous que le nom de la colonne que vous donnez à l'indexeur correspond exactement au nom de la DataColumn.
La mise en cache de la valeur semble également être presque deux fois aussi vite :
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Donc la méthode la plus efficace semble pour être :
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}