IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Problème d'affectation d'un champ générique


Sujet :

C#

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut Problème d'affectation d'un champ générique
    Bonjour,

    Je bute sur un problème de champ générique dans une classe.

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
        public class Field<T>
        {
            private string _name;
            private int _length;
            private T _value = null;
     
            public Field(string name, int length)
            {
                _name = name;
                _length = length;
            }
     
            public string Name
            {
                get
                {
                    return _name;
                }
            }
     
            public int Length
            {
                get
                {
                    return _length;
                }
            }
     
            public T Value
            {
                get
                {
                    return _value;
                }
            }
     
            public void SetValue(string value)
            {
                if (_value is string)
                {
    // Ca bloque ici
                    _value = (T)value;
                }
                else
                {
                    throw new TypeAccessException(string.Format("Unsupported type {0}.", _value.GetType().Name));
                }
            }
        }
    J'ai l'erreur suivante :
    Cannot convert type 'string' to 'T'
    Ma méthode SetValue va me servir à convertir une valeur au format "string" dans le type T.

    Je veux pouvoir utiliser les types standard "string", "int", etc. pour T, donc je ne peux pas remplacer T par une interface de mon cru, puisque je ne peux pas étendre les types de base.

    Le second problème se situe dans le get de Value : comment détecter que la _value n'a pas été initialisée ? Je ne peux pas l'initialiser à null, puisque T peut ne pas être nullable...

    Une idée ?

  2. #2
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Points : 460
    Points
    460
    Par défaut
    C'est normal que ca bloque.
    Comme tu l'as dit pour "null" T n'est pas déterminé à l'avance, le compilateur ne connait donc pas de cast de string vers T.

    A l'idéal il faudrait pouvoir contraindre T pour qu'il possède un opérateur de cast de string vers lui même. Mais ce genre de contrainte n'existe pas en C#.

    En revanche tu peux fournir a ta méthode SetValue, un paramètre supplémentaire, qui serait un convertisseur de string vers T

    Pour ce qui est de la deuxième partie de ta question, deux choses:
    - Tous les types ne sont pas nullable, int par exemple
    - Rien ne t'empêches d'avoir un booléen qui t'indiquera si le champs a été initialisé ou non.
    - Tu peux force l'initialisation par le constructeur.

    Dans tout les cas, rien n'empêche le développeur de réaliser l’équivalent d'un SetValue(null)

  3. #3
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 317
    Points
    13 317
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private T _value = default(T);
    puis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if (typeof(T).Equals(typeof(string))) // plus performant quee _value is string
    {
    	  object tmp = value;
    	  _value = (T)tmp;
    }
    else
    //etc ....

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Merci BlueDeep :cool:

    Le coup du constructeur "default" je connaissais pas du tout.

    Que se passe-t-il si mon T est un type dont aucun constructeur ne prends pas de paramètre ?
    (Si tu me dis que ça plante, tant mieux, c'est le but de ma question )

    Sinon, étrange qu'en passant par une variable temporaire de type object, C# arrive à faire la conversion...

    Quant à l'idée de antoine.debyser, elle m'a l'air plus propre que de passer par object temporaire (mais pas forcément plus rapide).
    Par contre, je n'ai absolument pas compris comment transposer les exemples de la MSDN ou les différents bouts de code trouvé sur google à ce sujet à mon problème...

  5. #5
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 317
    Points
    13 317
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Merci BlueDeep :cool:

    Le coup du constructeur "default" je connaissais pas du tout.
    default n'est pas un constructeur; c'est juste une astuce permettant de gérer les types génériques sans contrainte de type "where class", comme on ne peut pas savoir si T est un type nullable ou pas.
    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DateTime dt = null; // n'est pas autorisé
    DateTime dt = default(DateTime); // est  autorisé et equivalent à la déclaraion DateTime dt;
    string s = default(string); // équivalent à string s = null;
    Que se passe-t-il si mon T est un type dont aucun constructeur ne prends pas de paramètre ?
    Pas de soucis, default n'étant pas un constructeur (sauf pour les "struct").


    Sinon, étrange qu'en passant par une variable temporaire de type object, C# arrive à faire la conversion...
    Non, logique : tout est object, donc quelquse chose vers object passe dans tous les cas. object pouvant a priori être n'importe quoi, on peut toujours tenter un cast (et prendre une exception si ça foire).

  6. #6
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Ok, effectivement, dit comme ça c'est logique

    Et enfin, on est bien d'accord que j'ai pas moyen de faire plus propre que ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     
            public object CreateField()
            {
                switch (Type)
                {
                    case "string":
                        return (object)new Field<string>(Name, Length);
                    case "int":
                        return (object)new Field<int>(Name, Length);
                    case "decimal":
                        return (object)new Field<decimal>(Name, Length);
                    case "datetime":
                        return (object)new Field<DateTime>(Name, Length);
                    default:
                        throw new TypeAccessException("Unsupported data type");
                }
            }

  7. #7
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Points : 460
    Points
    460
    Par défaut
    Par rapport a ton dernier post :
    tu pourrais rajouter une interface, pour retourner quelques chose d'autre qu'object
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    interface IField
    {
       string Name { get; }
       int Length { get ; }
    }
     
    class Field<T> : IField
    {
     // ... //
    }
     
    public IField CreateField()
    {
      // ... //
    }
    Citation Envoyé par StringBuilder
    Par contre, je n'ai absolument pas compris comment transposer les exemples de la MSDN ou les différents bouts de code trouvé sur google à ce sujet à mon problème...
    Je penses avoir devenir ce que tu veux faire, du coup je tente un exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class Field<T>
    {
      // ... //
     
      public void SetValue(string value, Converter<string, T> converter)
      {
          _value = converter(value);
      }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public int IntFieldParser(string value)
    {
       int ret = 0;
       int.TryPars(value, out ret);
       return ret;
    }
    et du coup pourrait l'utiliser comme ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Field<int> champIndex = new Field<int>("Index",10);
    champIndex.SetValue("1234", new Converter<string, int>(IntFieldParser));
    Cela aurait pour effet d'affecter la valeur 1234 la proprieté Value de champIndex.
    C'est ce genre de chose que tu veux faire?

  8. #8
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    C'est effectivement ce que je tente de faire.

    Ça marche avec object, même si ton exemple est mieux.

    Je verrai lundi pour implémenter ta méthode, qui est un peu plus longue à écrire.

Discussions similaires

  1. Réponses: 3
    Dernier message: 04/04/2006, 09h39
  2. Affectation d'un champs blob dans une var de type TStrings
    Par Andry dans le forum Bases de données
    Réponses: 1
    Dernier message: 16/03/2005, 18h26
  3. problème d'affectation de tableau ...
    Par Mike888 dans le forum C
    Réponses: 23
    Dernier message: 26/02/2005, 14h52
  4. Entier 64 bits sous linux, problème d'affectation
    Par Steki-kun dans le forum Linux
    Réponses: 2
    Dernier message: 13/01/2005, 21h10
  5. [CR] Problème de sélection sur un champ date
    Par noluc dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 21/11/2003, 16h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo