Ayrıştırmayı kullanarak bir dizeyi herhangi bir türe dönüştürecek genel Parse () işlevi var mı?


91

Bir dizeyi genel dönüş türüne göre intveya dateveya buna longgöre genel bir türe dönüştürmek istiyorum .

Temelde böyle bir işlev Parse<T>(String), bir tür öğe döndürür T.

Örneğin, bir int geçirildiyse, işlev int.parsedahili olarak yapmalıdır .

Yanıtlar:


132

System.Convert.ChangeType

Örneğinize göre şunları yapabilirsiniz:

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

"Genel dönüş türü" gereksiniminizi karşılamak için kendi uzantı yönteminizi yazabilirsiniz:

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

Bu, şunları yapmanıza izin verecektir:

int i = "123".ChangeType<int>();

havalı, ama garip olan şey ChangeType, bu yüzden bu işlevin bir tür döküm yaptığını ve ayrıştırmadığını düşünürdüm
Karim

7
MSDN, kaynak nesnede doğru dönüştürme yöntemini bulan ve IConvertible arabirimini uygulamasını gerektiren bir sarmalayıcı olduğunu söylüyor.
Ani

Uygulanması IConvertablegerekiyorsa T, ie'yi de kısıtlamanız gerekmez mi T ChangeType<T>(this object obj) where T : IConvertable?
Liam

2
@Liam: Hayır, öyle objolmalı IConvertible, ancak bunu derleme sırasında belirlemenin bir yolu yok.
Ani

Hata durumunda null veya false döndüren TryChangeType gibi bir şeye ihtiyacım olursa? Sadece istisna yakalayarak mı?
Umutsuz

22

Görünüşe göre bu konuya cevap vermek için çok geç kaldım. Ama işte benim uygulamam:

Temel olarak, Object sınıfı için bir Extention yöntemi oluşturdum. Null yapılabilir, sınıflar ve yapı gibi tüm türleri işler.

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

O da "null" -aspect içeren nedeni IMHO bu iyi cevaptır
Ole Albers

TypeDescriptorNull yapılabilir türler ve null yapılamaz Convert.ChangeTypeolanlar için kullanmanızın belirli bir nedeni var mı? Bu trybloğun tamamı yalnızca TypeConverter2 satır koda indirgenebilir ve hem null yapılabilir hem de null yapılamaz .
IMujagic


8

Pranay'ın cevabının daha temiz versiyonu

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

.NET'te nesneleri bir türden diğerine dönüştürmek için kullanılan birkaç kural vardır.

Ancak bu yöntemler, tipik yöntemlerden çok daha yavaştır T.Parse(string), kutulamaya neden olur ve tek bir değeri her dönüştürmek istediğinizde çok sayıda ayırma gerektirir.

İçin ValueString , ben, yansıma kullanarak tipte uygun, statik ayrıştırma yöntemi bulmak çağırmak lambda ifade inşa etmek ve ileride kullanılmak üzere derlenmiş temsilci (Bkz önbelleğe seçti bu cevabı bir örnek için).

Ayrıca, türün uygun bir ayrıştırma yöntemi yoksa yukarıda bahsettiğim yöntemlere de geri dönüyor ( Benioku dosyasındaki performans bölümüne bakın ).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.