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.

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>();

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;
           }

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


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);
    }
}

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.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.