Pertanyaan ini muncul sesekali, tetapi saya belum melihat jawaban yang memuaskan.
Pola khas adalah (baris adalah DataRow ):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Pertanyaan pertama saya adalah mana yang lebih efisien (saya telah membalik kondisinya):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Ini menunjukkan bahwa .GetType () harus lebih cepat, tetapi mungkin kompiler tahu beberapa trik yang tidak saya lakukan?
Pertanyaan kedua, apakah layak untuk men-cache nilai baris ["value"] atau apakah kompiler mengoptimalkan pengindeks?
Sebagai contoh:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Catatan:
- baris ["value"] ada.
- Saya tidak tahu indeks kolom dari kolom (karenanya pencarian nama kolom).
- Saya bertanya secara khusus tentang memeriksa DBNull dan kemudian tugas (bukan tentang optimasi prematur, dll.).
Saya membandingkan beberapa skenario (waktu dalam detik, 10.000.000 uji coba):
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 memiliki kinerja yang sama dengan "=="
Hasil paling menarik? Jika Anda tidak cocok dengan nama kolom berdasarkan huruf (misalnya, "Nilai" dan bukan "nilai", dibutuhkan kira-kira sepuluh kali lebih lama (untuk string):
row["Value"] == DBNull.Value: 00:00:12.2792374
Moral dari cerita tersebut adalah bahwa jika Anda tidak dapat mencari kolom berdasarkan indeksnya, maka pastikan bahwa nama kolom yang Anda masukkan ke pengindeks sama persis dengan nama DataColumn.
Caching nilainya juga tampaknya hampir dua kali lebih cepat:
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Jadi metode yang paling efisien tampaknya menjadi:
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}
IDataRecord
ekstensi.