281 votes

Conversion générique de type FROM string

J'ai une classe que je veux utiliser pour stocker des "propriétés" pour une autre classe. Ces propriétés ont simplement un nom et une valeur. Idéalement, ce que je voudrais c'est de pouvoir ajouter dactylographié afin que la "valeur" renvoyée soit toujours du type que je souhaite.

Le type doit toujours être une primitive. Cette classe sous-classe une classe abstraite qui stocke essentiellement le nom et la valeur sous forme de chaîne. L'idée est que cette sous-classe ajoutera une certaine sécurité de type à la classe de base (ainsi qu'une économie sur la conversion).

J'ai donc créé une classe qui est (en gros) la suivante :

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

La question est donc la suivante :

Existe-t-il un moyen "générique" de reconvertir une chaîne de caractères en primitive ?

Je n'arrive pas à trouver d'interface générique qui lie la conversion à travers le tableau (quelque chose comme ITryParsable aurait été idéal !).

0 votes

Je serais intéressé de voir un exemple de votre classe concrète, même juste un extrait :)

0 votes

Pouvez-vous s'il vous plaît poster les parties pertinentes de votre classe de base ?

0 votes

Je me demande si quelqu'un peut faire fonctionner les réponses ici en .Net Standard 1.2 :/

450voto

lubos hasko Points 13669

Je ne suis pas sûr d'avoir bien compris vos intentions, mais voyons si celle-ci est utile.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}

0 votes

Cela fait quelques jours que je me demande comment désérialiser un flux en un type générique. Merci :)

3 votes

Je suis d'accord, bien que Convert.ChangeType n'est pas une solution très universelle et extensible, elle fonctionne pour la plupart des types de base. Si quelque chose de mieux est nécessaire, il n'y a aucun problème à intégrer cette méthode dans quelque chose de plus grand comme Tim l'a suggéré ou à utiliser une méthode de conversion différente.

20 votes

J'ajouterais sans aucun doute l'endroit où T:IConvertible

89voto

Tim Coker Points 331

La méthode de lubos hasko échoue pour les nullables. La méthode ci-dessous fonctionnera pour les nullables. Ce n'est pas moi qui l'ai inventée. Je l'ai trouvée via Google : http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Credit to "Toksoz au thon"

Utilisation en premier :

TConverter.ChangeType<T>(StringValue);  

La classe est ci-dessous.

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}

0 votes

J'ajouterais des options de conversion de repli pour les Enums et autres structures complexes, mais bon appel.

2 votes

Pourquoi le RegisterTypeConverter ? Devons-nous enregistrer les convertisseurs à l'avance ? (malheureusement le lien est mort, donc je n'ai pas pu me documenter sur le sujet)

0 votes

Pour les conversions multiples, vous devriez probablement créer tc (le TypeConverter ) une seule fois. TypeConverter est lent parce qu'il utilise la réflexion pour rechercher le fichier TypeConverterAttribute . Si vous initialisez un seul fichier privé TypeConverter vous devriez alors pouvoir réutiliser le champ TypeConverter à plusieurs reprises.

21voto

dbkk Points 5305

Pour de nombreux types (integer, double, DateTime etc), il existe une méthode Parse statique. Vous pouvez l'invoquer en utilisant la réflexion :

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}

4voto

Greg Hewgill Points 356191

Vous pouvez éventuellement utiliser une construction telle qu'un classe de traits . Ainsi, vous disposez d'une classe d'aide paramétrée qui sait comment convertir une chaîne de caractères en une valeur de son propre type. Votre getter pourrait alors ressembler à ceci :

get { return StringConverter<DataType>.FromString(base.Value); }

Je dois préciser que mon expérience des types paramétrés est limitée au C++ et à ses templates, mais j'imagine qu'il existe un moyen de faire le même genre de chose en utilisant les génériques du C#.

0 votes

Les versions génériques n'existent pas en C#.

0voto

Mastahh Points 17
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

J'utilise la conversion via un objet. C'est un peu plus simple.

0 votes

Merci je dois convertir un T dans une interface et la simple conversion objet T fonctionne correctement, facile et rapide merci

6 votes

(int)(object) "54" ; est une FATALITÉ, ce n'est pas VB !

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