Це питання виникає періодично, але я не побачив задовільної відповіді.
Типовою схемою є (рядок - це 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 () повинен бути швидшим, але, можливо, компілятор знає кілька хитрощів, яких я не знаю?
Друге питання, чи варто кешувати значення рядка ["value"] чи компілятор оптимізує індексатор все одно?
Наприклад:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Примітки:
- рядок ["значення"] існує.
- Я не знаю індекс стовпця стовпця (звідси пошук назви стовпця).
- Я запитую конкретно про перевірку наявності DBNull, а потім про призначення (а не про передчасну оптимізацію тощо).
Я визначив кілька сценаріїв (час у секундах, 1000000000 випробувань):
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
розширення.