Saya ingin melakukan sesuatu seperti ini:
myYear = record.GetValueOrNull<int?>("myYear"),
Perhatikan tipe nullable sebagai parameter generik.
Karena GetValueOrNull
fungsi tersebut dapat mengembalikan nol, upaya pertama saya adalah ini:
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
Tapi kesalahan yang saya dapatkan sekarang adalah:
Jenis 'int?' harus menjadi tipe referensi untuk menggunakannya sebagai parameter 'T' dalam tipe atau metode umum
Baik! Nullable<int>
adalah struct
! Jadi saya mencoba mengubah batasan kelas menjadi struct
batasan (dan sebagai efek samping tidak dapat kembali null
lagi):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Sekarang tugas:
myYear = record.GetValueOrNull<int?>("myYear");
Memberikan kesalahan berikut:
Jenis 'int?' harus merupakan tipe nilai yang tidak dapat dibatalkan untuk menggunakannya sebagai parameter 'T' dalam tipe atau metode umum
Apakah menetapkan jenis yang dapat dibatalkan sebagai parameter umum?
IDataRecord
DbDataRecord
Jawaban:
Ubah tipe pengembalian ke Nullable, dan panggil metode dengan parameter non nullable
sumber
Gunakan saja seperti ini:
sumber
GetValueOrDefault
untuk mengklarifikasi bahwa ia kembalidefault(T)
daripadanull
. Atau, Anda bisa meminta pengecualian jikaT
tidak dapat dibatalkan.Lakukan saja dua hal pada kode asli Anda - hapus
where
kendala, dan ubah yang terakhirreturn
darireturn null
menjadireturn default(T)
. Dengan cara ini Anda dapat mengembalikan tipe apa pun yang Anda inginkan.Omong-omong, Anda dapat menghindari penggunaan
is
dengan mengubahif
pernyataan Anda menjadiif (columnValue != DBNull.Value)
.sumber
return default
sudah cukup (Anda tidak perlu(T)
, kompiler akan mengambilnya dari tipe pengembalian tanda tangan).Penafian: Jawaban ini berfungsi, tetapi dimaksudkan hanya untuk tujuan pendidikan. :) Solusi James Jones mungkin adalah yang terbaik di sini dan tentu saja yang saya pilih.
dynamic
Kata kunci C # 4.0 membuat ini lebih mudah, jika kurang aman:Sekarang Anda tidak perlu petunjuk tipe eksplisit tentang RHS:
Bahkan, Anda bahkan tidak membutuhkannya sama sekali!
value
sekarang akan menjadi int, atau string, atau jenis apa pun yang dikembalikan dari DB.Satu-satunya masalah adalah bahwa hal ini tidak mencegah Anda menggunakan jenis yang tidak dapat dibatalkan pada LHS, dalam hal ini Anda akan mendapatkan pengecualian runtime yang agak buruk seperti:
Seperti halnya semua kode yang menggunakan
dynamic
: caveat coder.sumber
Hanya harus melakukan sesuatu yang luar biasa mirip dengan ini. Kode saya:
sumber
Saya pikir Anda ingin menangani tipe referensi dan tipe struct. Saya menggunakannya untuk mengkonversi string Elemen XML ke tipe yang lebih diketik. Anda dapat menghapus nullAlternative dengan refleksi. Penyedia format adalah untuk menangani ketergantungan budaya '.' atau pemisah ',' misalnya desimal atau int dan ganda. Ini mungkin berhasil:
Anda bisa menggunakannya seperti ini:
sumber
Ini mungkin sebuah utas yang mati, tetapi saya cenderung menggunakan yang berikut ini:
sumber
Saya sendiri mengalami masalah yang sama.
... = reader["myYear"] as int?;
bekerja dan bersih.Ini bekerja dengan jenis apa pun tanpa masalah. Jika hasilnya DBNull, hasilnya nol karena konversi gagal.
sumber
int v=reader["myYear"]??-1;
atau beberapa standar lain, bukan-1
. Namun, ini mungkin memunculkan masalah jika nilainyaDBNull
...Saya tahu ini sudah tua, tetapi di sini ada solusi lain:
Sekarang, Anda tidak peduli apakah
T
itu nilai atau tipe referensi. Hanya jika fungsi mengembalikan true, Anda memiliki nilai wajar dari database. Pemakaian:Pendekatan ini sangat mirip dengan
int.TryParse("123", out MyInt);
sumber
Beberapa kendala umum tidak dapat digabungkan dalam mode ATAU (kurang ketat), hanya dalam mode AND (lebih ketat). Berarti satu metode tidak dapat menangani kedua skenario. Batasan umum juga tidak dapat digunakan untuk membuat tanda tangan unik untuk metode ini, jadi Anda harus menggunakan 2 nama metode terpisah.
Namun, Anda dapat menggunakan batasan umum untuk memastikan bahwa metode tersebut digunakan dengan benar.
Dalam kasus saya, saya secara khusus ingin null dikembalikan, dan tidak pernah nilai default dari semua tipe nilai yang mungkin. GetValueOrDefault = buruk. GetValueOrNull = bagus.
Saya menggunakan kata "Null" dan "Nullable" untuk membedakan antara tipe referensi dan tipe nilai. Dan di sini adalah contoh dari beberapa metode ekstensi yang saya tulis yang memuji metode FirstOrDefault di kelas System.Linq.Enumerable.
sumber
Cara yang lebih pendek:
kembali
0
untukint
, dannull
untukint?
sumber