Saya memiliki kelas generik yang harus mengizinkan semua jenis, primitif atau sebaliknya. Satu-satunya masalah dengan ini adalah menggunakan default(T)
. Ketika Anda memanggil default pada tipe nilai atau string, itu menginisialisasinya ke nilai yang wajar (seperti string kosong). Saat Anda memanggil default(T)
suatu objek, ia mengembalikan null. Untuk berbagai alasan kita perlu memastikan bahwa jika ini bukan tipe primitif, maka kita akan memiliki contoh default dari tipe tersebut, bukan null. Ini percobaan 1:
T createDefault()
{
if(typeof(T).IsValueType)
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Masalah - string bukanlah tipe nilai, tetapi tidak memiliki konstruktor tanpa parameter. Jadi, solusi saat ini adalah:
T createDefault()
{
if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Tapi ini terasa seperti lumpur. Apakah ada cara yang lebih baik untuk menangani kotak tali?
is
kata kuncinya? Bukankah itu berguna di sini?if (typeof(T).IsValueType || typeof(T) == typeof(String)) { return default(T); } else { return Activator.CreateInstance<T>(); }
Belum teruji, tapi hal pertama yang terlintas dalam pikiran.
sumber
Anda dapat menggunakan enumerasi TypeCode . Panggil metode GetTypeCode di kelas yang menerapkan antarmuka IConvertible untuk mendapatkan kode jenis untuk instance kelas tersebut. IConvertible diimplementasikan oleh Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char, dan String, sehingga Anda dapat memeriksa tipe primitif menggunakan ini. Info lebih lanjut tentang " Pemeriksaan Jenis Generik ".
sumber
Secara pribadi, saya suka metode overloading:
public static class Extensions { public static String Blank(this String me) { return String.Empty; } public static T Blank<T>(this T me) { var tot = typeof(T); return tot.IsValueType ? default(T) : (T)Activator.CreateInstance(tot) ; } } class Program { static void Main(string[] args) { Object o = null; String s = null; int i = 6; Console.WriteLine(o.Blank()); //"System.Object" Console.WriteLine(s.Blank()); //"" Console.WriteLine(i.Blank()); //"0" Console.ReadKey(); } }
sumber
Saya tahu pertanyaan ini sudah lama, tetapi telah ada pembaruan.
Sejak C # 7.0 Anda dapat menggunakan
is
operator untuk membandingkan tipe. Anda tidak lagi memerlukan penggunaantypeof
seperti pada jawaban yang diterima.public bool IsObjectString(object obj) { return obj is string; }
https://docs.microsoft.com/en-US/dotnet/csharp/language-reference/keywords/is
sumber
Diskusi untuk String tidak berfungsi di sini.
Saya harus memiliki kode berikut untuk obat generik agar berfungsi -
private T createDefault() { { if(typeof(T).IsValueType) { return default(T); } else if (typeof(T).Name == "String") { return (T)Convert.ChangeType(String.Empty,typeof(T)); } else { return Activator.CreateInstance<T>(); } } }
sumber
String
berdasarkan nama, terutama tanpa memperhatikan namespace itu buruk. Dan saya juga tidak suka cara Anda pindah agama.