148 votes

Convertir une chaîne en type nullable (int, double, etc ...)

Je suis tenter de faire certains de conversion de données. Malheureusement, une grande partie des données est dans les cordes, où il doit être de type int ou double, etc...

Donc, ce que j'ai est quelque chose comme:

double? amount = Convert.ToDouble(strAmount);

Le problème avec cette approche est que si strAmount est vide, si il est vide je le veux à somme nulle, donc quand je l'ajouter dans la base de données de la colonne sera null. Donc j'ai fini par écrire ceci:

double? amount = null;
if(strAmount.Trim().Length>0)
{
    amount = Convert.ToDouble(strAmount);
}

Maintenant cela fonctionne bien, mais j'ai maintenant cinq lignes de code au lieu d'un. Cela rend les choses un peu plus difficile à lire, surtout quand j'ai une grande quantité de colonnes à convertir.

Je pensais utiliser une extension de la classe string et générique de passer dans le type, c'est parce qu'il pourrait être un double, ou un int ou un long. J'ai donc essayé ceci:

    public static class GenericExtension
    {
        public static Nullable<T> ConvertToNullable<T>(this string s, T type) where T: struct
        {
            if (s.Trim().Length > 0)
            {
                return (Nullable<T>)s;
            }
            return null;
        }
    }

Mais je reçois l'erreur: Impossible de convertir le type 'string' à 'T?'

Est-il un moyen de contourner cela? Je ne suis pas très familier avec la création de méthodes utilisant des génériques.

164voto

Joel Coehoorn Points 190579

Une autre chose à garder à l'esprit est que la chaîne elle-même pourrait être nulle.

 public static Nullable<T> ToNullable<T>(this string s) where T: struct
{
    Nullable<T> result = new Nullable<T>();
    try
    {
        if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0)
        {
            TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
            result = (T)conv.ConvertFrom(s);
        }
    }
    catch { } 
    return result;
}
 

57voto

Michael Meadows Points 15277

Vous pouvez essayer d'utiliser la méthode d'extension ci-dessous:

 public static T? GetValueOrNull<T>(this string valueAsString)
    where T : struct 
{
    if (string.IsNullOrEmpty(valueAsString))
        return null;
    return (T) Convert.ChangeType(valueAsString, typeof(T));
}
 

De cette façon, vous pouvez le faire:

 double? amount = strAmount.GetValueOrNull<double>();
int? amount = strAmount.GetValueOrNull<int>();
decimal? amount = strAmount.GetValueOrNull<decimal>();
 

29voto

John Kraft Points 4559

Et ça:

 
double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);
 

Bien sûr, cela ne prend pas en compte l'échec de la conversion.

23voto

TheSoftwareJedi Points 15921

J'ai écrit ce convertisseur de type générique. Il fonctionne avec les valeurs Nullable et Standard, convertissant entre tous les types convertibles - pas seulement les chaînes. Il gère toutes sortes de scénarios auxquels vous vous attendez (valeurs par défaut, valeurs nulles, autres valeurs, etc.)

Je l’utilise depuis environ un an dans des dizaines de programmes de production, alors ça devrait être assez solide.

     public static T To<T>(this IConvertible obj)
    {
        Type t = typeof(T);

        if (t.IsGenericType
            && (t.GetGenericTypeDefinition() == typeof(Nullable<>)))
        {
            if (obj == null)
            {
                return (T)(object)null;
            }
            else
            {
                return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(t));
            }
        }
        else
        {
            return (T)Convert.ChangeType(obj, t);
        }
    }

    public static T ToOrDefault<T>
                 (this IConvertible obj)
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return default(T);
        }
    }

    public static bool ToOrDefault<T>
                        (this IConvertible obj,
                         out T newObj)
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = default(T);
            return false;
        }
    }

    public static T ToOrOther<T>
                           (this IConvertible obj,
                           T other)
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return other;
        }
    }

    public static bool ToOrOther<T>
                             (this IConvertible obj,
                             out T newObj,
                             T other)
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = other;
            return false;
        }
    }

    public static T ToOrNull<T>
                          (this IConvertible obj)
                          where T : class
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return null;
        }
    }

    public static bool ToOrNull<T>
                      (this IConvertible obj,
                      out T newObj)
                      where T : class
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = null;
            return false;
        }
    }
 

10voto

Andrew Bullock Points 14899

Vous pourriez vouloir essayer:

 TypeConverter conv = TypeDescriptor.GetConverter(typeof(int));
conv.ConvertFrom(mystring);
 

faites votre propre contrôle nul et retournez int? si nécessaire. Vous voudrez également emballer cela en try {}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X