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 :

Liste paramètres imbriqués


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut Liste paramètres imbriqués
    Bonjour,

    C'est la première fois que je poste sur ce forum.
    Mais ce dernier m'a toujours aidé ^^
    (j'espère cette fois encore ^^)

    Niveau programmation objet fortement typé, j'utilise Java.
    Pour un projet je dois utiliser C# (framework 4.0 ^^).
    Je sais que les deux ne sont pas très différents mais quand même ^^
    (J'ai lu la quasi totalité de la spec ^^')

    Je ne lancerai pas de Troll ^^,
    les deux ont leurs faiblesses et leurs avantages ^^

    Voila mon problème,
    J'ai un objet paramétrable (ou générique en C#)
    Appelons le «Obj<T>»

    J'aimerai stocker plusieurs instances de «Obj»
    mais avec des paramètres différents (String, Double, ...)

    En Java je sais faire,
    En C#, ..., là je bloque =/
    Les types paramétrés ne sont pas gérés de la même manière,
    Et donc C# ne dispose pas de la «Wildcard» de Java («?»)

    Voila en Java ce que ça donnerait :

    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
     
    public class Obj<T> {
     
    	T obj = null;
     
    	public Obj(T obj) {
    		super();
    		this.obj = obj;
    	}
     
    	public T method() {
    		return obj;
    	}
     
    	public static void main(String[] args) {
    		Obj<Double> o1 = new Obj<Double>((double) 25.2);
    		Obj<String> o2 = new Obj<String>("coucou");
     
    		List<Obj<?>> list = new ArrayList<Obj<?>>();
    		list.add(o1);
    		list.add(o2);
     
    		for (Obj<?> obj : list) {
    			System.out.println(obj.method());
    		}
    	}
    }
    En C#,
    J'ai seulement réussi à les stocker en temps qu'Object.
    Il ne perd pas les types,
    Mais je dois obligatoirement coder en dur le cast avec le bon type
    (pas possible en générique)
    Et puis bon, se trimballer avec des Object,
    Ça perd tout le charme des templates Oo

    Voila, si quelqu'un à une solution je suis preneur ^^
    Je ne reste pas bloqué sur un stockage par liste,
    Si il y a un autre moyen je testerai volontier.

    Merci.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Il n'y a pas d'équivalent à ça en C#. C'est lié à la façon dont les génériques sont implémentés : en Java, la VM n'a aucune connaissance des génériques, c'est juste une astuce du compilateur qui introduit automatiquement des cast là où c'est nécessaire. Alors qu'en C#, le CLR (la VM si tu préfères) gère nativement les génériques, aucun cast n'est effectué : le runtime crée réellement un nouveau type pour chaque paramètre de type que tu utilises (i.e. Obj<int> et Obj<string> seront vraiment 2 types différents, alors qu'en Java ce serait en fait le même type), et ces types n'ont pas de relation entre eux (ils n'héritent pas d'une classe de base commune par exemple)

    Ça perd tout le charme des templates Oo
    Les génériques ressemblent aux templates, mais c'est un mécanisme différent...


    Pour régler ton problème, voilà ce que je te suggère :

    - crée une interface non générique (par exemple IObj), dans laquelle tu définis la méthode "method" avec un type de retour "object"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public interface IObj
    {
        object method();
    }
    - dans ta classe Obj<T>, implémente cette interface explicitement. Cela te permet notamment de déclarer également une méthode "method" avec le type de retour que tu veux :

    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 class Obj<T> : IObj
    {
     
            ...
     
    	public T method()
            {
    		return obj;
    	}
     
            // Implémentation explicite
            object IObj.method()
            {
                return this.method();
            }
     
            ...
    }
    - A la place de List<Obj<?>>, utilise List<IObj> :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	public static void Main(string[] args)
            {
    		Obj<double> o1 = new Obj<double>(25.2);
    		Obj<string> o2 = new Obj<string>("coucou");
     
    		IList<IObj> list = new List<IObj>();
    		list.Add(o1);
    		list.Add(o2);
     
    		foreach (IObj obj in list)
                    {
    			Console.WriteLine(obj.method());
    		}
            }

  3. #3
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    Génial Oo

    Je me disais bien aussi que c'était faisable en C# aussi ^^
    C'est un peu détourné mais ça fonctionne (c'est le principal ^^)

    Pour ce qui est de l'implémentation des génériques,
    Oui oui j'ai bien lu tout ça ^^

    Et bien je te remercie ^^
    Et c'est encore une fois une victoire grâce à vous ^^

  4. #4
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    Hum, en fait si je fais comme ça,
    Je perd le typage dans ma classe =/

    Je m'explique,

    Dans ma classe Obj<T>,
    J'ai une liste d'un autre objet typé, appelons le AObj<T>.

    Cette liste à un type fixe qui est spécifié par Obj.
    Si j'utilise une interface qui de-spécialise ma classe Obj,
    je perds aussi le type de ma liste.

    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
     
    public class AObj<T>
    {
      ...
    }
     
    public interface IObj
    {
      IList<AObj<object>> Buffers { get; }
      object method();
    }
     
    public class Obj<T> : IObj
    {
      public IList<AObj<T>> Buffers { get; private set; }
      public T method()
      {
        ...
      }
     
      IList<AObj<object>> IObj.Buffers
      {
        // ça il ne veut pas, et avec un cast ça plante =/
        get { return this.Buffers; }
      }
      object IObj.method()
      {
        return this.method();
      }
    }
    J'ai essayé de refaire une autre interface IAObj mais,
    D'une ça poserait problème du fait que la liste pourrai contenir différents types
    Et d'autre part, bah ça fonctionne pas xD (enfin je l'ai peut être mal fait Oo)

    Bon voila ^^
    Je suis re bloqué quasi au même point =/

    Merci de votre aide

  5. #5
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    Bonjour,

    Je relance mon problème en quête de réponses ^^
    J'en profite pour remettre à plat mon problème

    J'ai un objet Box Module, qui contient un nombre indéterminé d'objets Input et Output.
    Ces deux derniers héritent d'un objet IO qui lui contient un nombre indéterminé d'objets Buffer.
    Ce dernier possède une liste d'objet Bloc qui lui est typé.


    Voila en gros le diagramme ^^

    Donc tout le monde est typé sauf Module
    Et Module peut contenir des Input et des Output de type différents.

    Avec la méthode précédente, je me retrouve avec l'obligation d'avoir des Buffer de Bloc d'Object =/

    Merci de votre aide ^^

  6. #6
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Avant tout je présume qu'un IO<Int32> ne se réfère qu'à des Buffer<Int32>, qui lui-même ne contient que des Bloc<Int32>, n'est-ce pas ? Et donc seul Module mélange des génériques avec des arguments différents.

    Dans ce cas, c'est simple : liste toutes les fonctions et propriétés consommées par Module et place-les dans une ou plusieurs interfaces non-génériques. Et pour reprendre ta question précédente, ton IObj.Buffers aurait dû renvoyer un IList<IObj>. Songe à l'implémentation explicite des interfaces si tu veux conserver une propriété Buffer générique tout en implémentant une version non-générique pour l'interface. Et facilite-toi la vie avec la covariance des génériques (un IList<Obj<Int32>> peut être implicitement casté en un IList<IObj>)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2003] comportement différent suivant les pc - liste paramétrée
    Par Dermochelys dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 04/04/2011, 13h35
  2. [AC-2003] Table avec un champ liste paramétré
    Par lio33 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 17/06/2010, 15h24
  3. (Reports) 2 paramètres imbriqués dans un reborts
    Par floflo164 dans le forum Reports
    Réponses: 5
    Dernier message: 14/01/2009, 18h06
  4. Listes paramétrées et conversions
    Par TheSeb dans le forum Langage
    Réponses: 4
    Dernier message: 12/09/2007, 17h00
  5. Comment obtenir la liste des paramètres d'une SP ?
    Par Le Gritche dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/03/2003, 16h54

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