To pytanie pojawia się czasami, ale nie widziałem satysfakcjonującej odpowiedzi.
Typowy wzorzec to (row to DataRow ):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Moje pierwsze pytanie brzmi, co jest bardziej wydajne (odwróciłem warunek):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Oznacza to, że .GetType () powinno być szybsze, ale może kompilator zna kilka sztuczek, których ja nie mam?
Drugie pytanie, czy warto buforować wartość wiersza [„wartość”], czy i tak kompilator optymalizuje indeksator?
Na przykład:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Uwagi:
- istnieje wiersz [„wartość”].
- Nie znam indeksu kolumny (stąd wyszukanie nazwy kolumny).
- Pytam konkretnie o sprawdzenie DBNull, a następnie przypisanie (nie o przedwczesną optymalizację itp.).
Porównałem kilka scenariuszy (czas w sekundach, 10 000 000 prób):
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 ma taką samą wydajność jak „==”
Najciekawszy wynik? Jeśli nie dopasujesz nazwy kolumny według wielkości liter (na przykład „Wartość” zamiast „wartość”, trwa to około dziesięć razy dłużej (w przypadku ciągu):
row["Value"] == DBNull.Value: 00:00:12.2792374
Morał z tej historii wydaje się być taki, że jeśli nie możesz wyszukać kolumny według jej indeksu, upewnij się, że nazwa kolumny, którą przekazujesz indeksatorowi, dokładnie odpowiada nazwie kolumny DataColumn.
Buforowanie wartości również wydaje się być prawie dwa razy szybsze:
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Wydaje się więc, że najbardziej wydajną metodą jest:
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}
IDataRecord
rozszerzenia.