Этот вопрос возникает время от времени, но я не нашел удовлетворительного ответа.
Типичный шаблон (строка - 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
расширения. - person nawfal   schedule 01.12.2017