Apakah ada fungsi Parse () generik yang akan mengonversi string menjadi tipe apa pun menggunakan parse?

91

Saya ingin mengonversi string menjadi tipe generik seperti intatau dateatau longberdasarkan tipe kembalian generik.

Pada dasarnya fungsi seperti Parse<T>(String)itu mengembalikan jenis item T.

Misalnya jika int telah diteruskan fungsi harus dilakukan secara int.parseinternal.

Karim
sumber

Jawaban:

132

System.Convert.ChangeType

Sesuai contoh Anda, Anda dapat melakukan:

int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));

Untuk memenuhi persyaratan "jenis pengembalian generik", Anda dapat menulis metode ekstensi Anda sendiri:

public static T ChangeType<T>(this object obj)
{
    return (T)Convert.ChangeType(obj, typeof(T));
}

Ini akan memungkinkan Anda untuk melakukan:

int i = "123".ChangeType<int>();
Ani
sumber
keren, tapi anehnya namanya ChangeType, jadi saya akan berpikir bahwa fungsi ini melakukan semacam cast dan tidak mengurai
Karim
7
MSDN mengatakan itu hanyalah pembungkus yang menemukan metode konversi yang tepat pada objek sumber, yang mengharuskannya mengimplementasikan antarmuka IConvertible.
Ani
Jika perlu diimplementasikan, IConvertablebukankah seharusnya Anda juga membatasi T, yaitu T ChangeType<T>(this object obj) where T : IConvertable?
Liam
2
@Liam: Tidak, itu objpasti IConvertible, tapi tidak ada cara untuk menentukannya pada waktu kompilasi.
Ani
jika saya membutuhkan sesuatu seperti TryChangeType yang mengembalikan null atau false dalam kasus gagal? Hanya dengan menangkap pengecualian?
Putus asa
22

Sepertinya saya terlambat untuk menjawab di utas ini. Tapi inilah implementasi saya:

Pada dasarnya, saya telah membuat metode Extention untuk kelas Object. Ini menangani semua tipe, yaitu nullable, class, dan struct.

 public static T ConvertTo<T>(this object value)
           {
               T returnValue;

               if (value is T variable)
                   returnValue = variable;
               else
                   try
                   {
                       //Handling Nullable types i.e, int?, double?, bool? .. etc
                       if (Nullable.GetUnderlyingType(typeof(T)) != null)
                       {
                           TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
                           returnValue = (T) conv.ConvertFrom(value);
                       }
                       else
                       {
                           returnValue = (T) Convert.ChangeType(value, typeof(T));
                       }
                   }
                   catch (Exception)
                   {
                       returnValue = default(T);
                   }

               return returnValue;
           }
Pranay Deep
sumber
IMHO ini adalah jawaban yang lebih baik karena ini juga berisi aspek "nullable"
Ole Albers
apakah ada alasan khusus mengapa Anda menggunakan TypeDescriptortipe nullable dan Convert.ChangeTypenon-nullable? Seluruh tryblok ini hanya dapat dikurangi menjadi TypeConverter2 baris kode dan akan bekerja untuk keduanya, nullable dan non-nullable.
IMujagic
9

System.Convert.ChangeTypetidak dikonversi ke tipe apa pun. Pikirkan hal-hal berikut:

  • tipe nullable
  • enums
  • Panduan dll.

Konversi ini dimungkinkan dengan penerapan ChangeType ini .

Alex Siepman
sumber
8

versi lebih bersih dari jawaban Pranay

public static T ConvertTo<T>(this object value)
{
    if (value is T variable) return variable;

    try
    {
        //Handling Nullable types i.e, int?, double?, bool? .. etc
        if (Nullable.GetUnderlyingType(typeof(T)) != null)
        {
            return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
        }

        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch (Exception)
    {
        return default(T);
    }
}
Eonasdan
sumber
0

Ada beberapa konvensi di .NET untuk mengonversi objek dari satu jenis ke jenis lainnya.

Tetapi metode ini jauh lebih lambat daripada biasanya T.Parse(string), menyebabkan tinju dan melibatkan banyak alokasi setiap kali Anda ingin mengonversi satu nilai.

Untuk ValueString , saya memilih untuk menemukan metode parsing statis yang sesuai dari tipe tersebut menggunakan refleksi, membangun ekspresi lambda yang memanggilnya dan menyimpan cache delegasi yang dikompilasi untuk digunakan di masa mendatang (Lihat jawaban ini sebagai contoh).

Itu juga mundur ke cara yang saya sebutkan di atas jika jenisnya tidak memiliki metode parsing yang sesuai (Lihat bagian kinerja di readme).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Şafak Gür
sumber