Этот вопрос возникает иногда, но я не нашел удовлетворительного ответа.
Типичный шаблон (строка - 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?
Во-вторых, стоит ли кэшировать значение строки [ "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 имеет такую же производительность, как "=="
Самый интересный результат? Если вы не учитываете имя столбца в отдельности (например, "Значение" вместо "значение", оно занимает примерно в десять раз дольше (для строки):
row["Value"] == DBNull.Value: 00:00:12.2792374
Мораль этой истории, похоже, состоит в том, что если вы не можете найти столбец по его индексу, убедитесь, что имя столбца, которое вы передаете индектору, точно совпадает с именем DataColumn.
Кэширование значения также кажется почти дважды столь же быстрым:
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();
}