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