none
conversion de List<quelconque> en List<Object> ? RRS feed

  • Question

  •  

    J'essaie que ma List<List<Object>> puisse accueillir des List d'objets de toutes natures en profitant des possibilités offerte par la classe Object et le système d'héritage.

     

    Exemple :

     

    List<List<Object>> ListExtern1 = new List<List<Object>>();

    ListExtern1.Add(new List<String>());

    ListExtern1.Add(new List<int>());

    ListExtern1.Add(new List<truc>());

    ListExtern1.Add(new List<machin>());

    ListExtern1.Add(new List<Object>());

     

    Mais le compilateur refuse car il ne peut pas convertir telle List<quelconque> en List<Object>.

     

    Comment profiter de la classe de base Object sans définir des centaines d'opérateurs de conversions ?

    (une pour chaque type de List)

     

     

    Merci.

     

    mercredi 6 août 2008 14:27

Toutes les réponses

  • La classe Object est la classe de base, c'est étrange qu'il ne veut pas faire la conversion. Es-ce que cela fonctionne pour les String et les Int?
    mercredi 6 août 2008 14:46
    Modérateur
  • Voici le message d'erreur que je reçois :

     

     

    Erreur 1 Impossible de convertir le type 'System.Collections.Generic.List<string>' en 'System.Collections.Generic.List<object>' C:\Documents and Settings\Bob\Local Settings\Application Data\Temporary Projects\ListDeList3\Class1.cs 21 29 ListDeList3

     

    mercredi 6 août 2008 14:58
  • Es-ce que tu pourrais essayer ceci :

    Code Snippet

    ListExtern1.Add((List<Object>)new List<String>());



    mercredi 6 août 2008 15:51
    Modérateur
  • Message d'erreur identique.

     

    mercredi 6 août 2008 16:58
  • Bonjour,

      Un peu de code :

    Code Snippet

    //Version "cast" qui ne marche mais change pas trop la liste finalement :

    List<List<Object>> ListExtern1 = new List<List<object>>();

    ListExtern1.Add((new List<string>()).Cast<object>().ToList<object>());

    //TEST : ListExtern1.Add(typeof(string), new List<string>().ToArray().ToList<object>());

    //Voir en terme de perf mais je pense que ca ne changera pas grand chose

    //dans tout les cas tu vas faire un cast en list<object>.....ta liste sera bien de type "object"

    ListExtern1.Add((new List<int>()).Cast<object>().ToList<object>());

    ListExtern1.Add((new List<DateTime>()).Cast<object>().ToList<object>());

    ListExtern1.Add((new List<object>()).Cast<object>().ToList<object>());

     

    ListExtern1[0].Add("hello");

    ListExtern1[0].Add(5); //ca marche aussi :(

    ListExtern1[1].Add(5);

    ListExtern1[2].Add(DateTime.Now);

    object obj = new object();

    ListExtern1[3].Add(obj);

     

     

    //Avec ceci ca marche pareil en fait :

    List<List<Object>> ListExtern1 = new List<List<object>>();

    ListExtern1.Add(new List<object>());

    ListExtern1.Add(new List<object>());

    ListExtern1.Add(new List<object>());

    ListExtern1.Add(new List<object>());

     

    ListExtern1[0].Add("hello");

    ListExtern1[0].Add(5);

    ListExtern1[1].Add(5);

    ListExtern1[2].Add(DateTime.Now);

    object obj = new object();

    ListExtern1[3].Add(obj);

     

     

    //Plus propre a mon sens avec Dictionnaire :

    Dictionary<Type, List<Object>> ListExtern1 = new Dictionary<Type, List<object>>();

    ListExtern1.Add(typeof(string), new List<object>());

    ListExtern1.Add(typeof(int), new List<object>());

    ListExtern1.Add(typeof(DateTime), new List<object>());

    ListExtern1.Add(typeof(object), new List<object>());

    ListExtern1[typeof(DateTime)].Add(DateTime.Now);

    ListExtern1[typeof(int)].Add(5);

    ListExtern1[typeof(string)].Add("hello");

    object obj = new object();

    ListExtern1[typeof(object)].Add(obj);

     

     

    string date = (ListExtern1[typeof(DateTime)] as DateTime).ToShortDateString();

     

     

    Attention donc dans ces exemples tu as toujours au final une list<object> et tu peux donc y ajouter soit un string soit un int ca ne bloque pas! je suppose que ca ne fait pas vraiment ce que tu souhaites mais ca enregistre bien les données dans la liste (cf la toute dernière ligne de code, un cast d'un item de la liste permet bien d'avoir le type "natif" de l'object que tu y as mis Wink un petit .GetType() te retournerai bien DateTime dans cet exemple)

     

    Ne sachant pas ton besoin je suis peut-être un poil a coté de la plaque Wink

    A+,

          Stéphane

     

    PS: je ne dis pas qu'on ne peut pas faire de cast d'une List<string> en List<object> je propose juste un contournement a ton message d'erreur Big Smile

    mercredi 6 août 2008 19:26
  • Oulalala... je cogite moi ce soir Wink

    Bon c'est moins beau et aussi bien ca n'ira avec ce que tu veux faire de ces listes mais :

    Code Snippet

    System.Collections.Hashtable hashTest = new System.Collections.Hashtable();

    hashTest.Add(typeof(string), new List<string>());

    hashTest.Add(typeof(int), new List<int>());

    hashTest.Add(typeof(DateTime), new List<DateTime>());

    (hashTest[typeof(string)] as List<string>).Add("hello");

    (hashTest[typeof(string)] as List<string>).Add(5); //ca passe pas a la compilation ;)

    (hashTest[typeof(int)] as List<int>).Add(5);

    (hashTest[typeof(int)] as List<int>).Add("toto"); //contrairement a tout a l'heure la ca ne passe pas non plus a la compilation :D

    (hashTest[typeof(DateTime)] as List<DateTime>).Add(DateTime.Now);

     

     

    Voila c'est tout ce qui me viens a l'esprit pour l'instant pour avoir une liste de liste d'objets de type différents propre sur elle (pas clair ? Wink )

     

    ++,

         Stéphane

    mercredi 6 août 2008 19:31
  • et pourquoi pas tout simplement ?

     

    List<IList> maList = new List<IList>();

     

     

     

    jeudi 7 août 2008 07:47
  •  Sebastien FERRAND A écrit:

    et pourquoi pas tout simplement ?

    List maList = new List();

    J'y avais pensé mais :

    - IList requiert le type des items de la list (tout comme list)

    Code Snippet

    List<IList<object>> malist = new List<IList<object>>();

     

     

    - A l'execution j'ai eu ceci :

    Code Snippet

    List<IList<object>> malist = new List<IList<object>>();

    malist.Add((IList<object>)new List<string>()); //Exception ici

    malist.Add((IList<object>)new List<int>());

    (malist[0] as List<string>).Add("test1");

    (malist[1] as List<int>).Add(2);

    (malist[0] as List<string>).Add("test3");

     

     

    System.InvalidCastException was unhandled
      Message="Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IList`1[System.Object]'."
      Source="App1"
      StackTrace:
           at App1.Form1.Form1_Load(Object sender, EventArgs e) in C:\Documents and Settings\admsbilles\My Documents\Visual Studio 2008\Projects\MSDN_Forums_Test\App1\Form1.cs:line 22
    (...)

     

    Je me trompe peut-être dans l'ajout des listes dans la liste mais il me semble (la encore je peux me tromper) que IList n'est qu'une interface que List implémente et le problème reste le même Wink

     

    A+,

        Stéphane

    jeudi 7 août 2008 08:05
  • non non...

    pas

    Code Snippet
    System.Collections.Generics.IList<>

     

     

    mais

    Code Snippet
    System.Collections.IList.

     

     

     

    Ainsi, tu peux faire :

    Code Snippet

    List<IList> maList = new List<IList>();

    maList.Add(new List<string>());

    maList.Add(new List<object>());

     

     

     

     

    Sébastien

    jeudi 7 août 2008 08:44
  • re Wink

    Ah ok, ben j'connaissais même pas cet IList la Wink autant pour moi donc Big Smile

    Et merci pour l'info ca peut servir (même si je ne suis pas le posteur de la question et même si je reste sur mon idée qu'il y a trop de risque a parcourir la liste par index, c'est un coup a mettre un string dans un int je trouve Sad )

    ++,

        Stéphane

    jeudi 7 août 2008 09:24
  • je suis d'accord... pour moi procéder ainsi est dangereux et inutile.

    il est préférable d'utiliser des collections spécifiques pour chaque utilisation.

     

    sébastien

     

    jeudi 7 août 2008 09:29
  • Tu peux pas convertir un IList<quelquechose> en IList<Object> car les génériques sont fait pour empêcher aux problèmes de cast de faire leur apparition dès la compilation.
    Si tu fais :
    IList<string> malistedestrings = new
    IList<string>();
    ... tu ne pourras mettre que des objets de type string dans ta liste... et c'est le but des génériques.
    On appelle ça le principe de type-safe.
    C'est la raison pour laquelle tu ne peux pas faire ça :
    IList<Object>
    malistedestrings = new IList<string>();
    Parce que ça voudrait dire que tu pourrais faire ceci :
    malistedestrings.Add(12);
    En castant, tu pourrais donc ajouter un entier à une liste censée ne contenir que des strings... pas très type safe tout ça...
    ceci-dit, c'est clair que c'est quand même chiant tout ça :-)
    mercredi 20 août 2008 08:46