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 :

Cast et Array


Sujet :

C#

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut Cast et Array
    Bonjour,
    un truc que je ne pige pas! Pourquoi ne peut-on pas caster un tableau d'objet.

    Par ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    static void Main( string[] args )
    {
                ArrayList oList = new ArrayList();
     
                for (int i = 0; i < 100; i++)
                    oList.Add( i );
     
                int[] o = (int[])oList.ToArray();
    ....
    }
    ne compile pas car "Impossible de convertir le type 'object[]' en 'int[]'

    de même un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     int[] o = oList.ToArray() as int[]
    ne compile pas

    En fait j'ai remarqué ce comportement en codant une méthode générique
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return new List<T>( p_oList.ToArray() as T[] );
    compile mais renvoi une exception car
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     p_oList.ToArray() as T[]
    renvoi null

    J'aimerai bien comprendre le pourquoi de tout ça...
    Merci de vos éclaircissements

  2. #2
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    C'est assez simple. int est un type. int[] est un autre type. Bien qu'un tant qu'humain on voit la relation que l'un est un tableau de l'autre, ce sont deux types différents.

    Par contre, si tu veux facilement convertir un tableau d'un type vers un tableau d'un autre type tu peux utiliser Array.ConvertAll comme décrit ci-dessous:

    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 static TOutput[] ConvertAll<TInput,TOutput> (
    	TInput[] array,
    	Converter<TInput,TOutput> converter
    )
     
    */
    public static void Main()
        {
            PointF[] apf = {
                new PointF(27.8F, 32.62F),
                new PointF(99.3F, 147.273F),
                new PointF(7.5F, 1412.2F) };
     
            Console.WriteLine();
            foreach( PointF p in apf )
            {
                Console.WriteLine(p);
            }
     
            Point[] ap = Array.ConvertAll(apf, 
                new Converter<PointF, Point>(PointFToPoint));
     
            Console.WriteLine();
            foreach( Point p in ap )
            {
                Console.WriteLine(p);
            }
        }
    De cette façon, le framework va construire un nouvel Array en castant chaque élément, un par un.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    Oui suis bien d'accord que int et int[] sont deux types distincts. Je suis cependant étonné que l'on puisse effectuer un cast de object vers int
    et que l'on ne puisse pas entre object[] et int[].

    Pour l'exemple que tu mentionnes la conversion est différente, puisqu'il s'agit de 2 structures et que donc le cast entre les 2 n'est pas possible.

    En effet le code suivant ne compile pas :

    object oPoint = new PointF( 27.8F, 32.62F );
    Point jPoint = (Point)oPoint;

  4. #4
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par karlus Voir le message
    object oPoint = new PointF( 27.8F, 32.62F );
    Point jPoint = (Point)oPoint;
    Si, ca doit compiler, par contre, au runtime tu auras une exception.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    Suis d'accord ça va compiler et planter à l'exécution. Mais je saisi pas pourquoi le comportement n'est pas le même entre 2 types tableaux.

  6. #6
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Pour ton exemple, je ferais ceci.

    Après, si utilises régulièrement ce type de conversion, libre à toi de créer un type myobject[] et d'y implémenter l'opérateur de cast vers int[].

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    ArrayList list = new ArrayList();
     
                for (int i = 0; i < 100; i++)
                {
                    list.Add(i);
                }
     
                int[] intlist = Array.ConvertAll<object, int>(list.ToArray(), delegate(object o) { return (int) o; });
    Le problème aussi c'est d'utiliser ArrayList, tu n'est pas à l'abris d'un type qui ne peut pas etre convertit en int et la c'est l'exception.

    A ta place, j'utiliserais des lists typés en bénéficiant pleinement des generics.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    ArrayList c'est bien mais techniquement ce n'est pas tout à fait un object[].

    Alors un cast entre un ArrayList et un tableau est pas possible.

    Ensuite pourquoi il est impossible de caster object[] en int[] et bien la réponse a deja été dite... ce sont deux types. Le probleme c'est qu'il sais que ce sont des types Tableaux. Il ne peut pas t'autoriser à faire un object[] int[] car en plus de la conversion du conteneur, il faudrait caster le contenu...
    Ce qu'il ne peut pas faire dans la mesure où le contenu est inconnu à la compilation, et en plus object[] autorise TOUTE sorte de chose alors que int[] autorise que des int... ce qui lui pose un autre problème.

    Cependant utiliser les listes génériques ne règlera pas son problème de cast. En effet ...
    List<object> oList = new List<object>();
    List<int> iList = (List<int>)oList;
    n'est pas possible non plus, on en reviens au même problème, c'est même encore pire ici car tu es passé par le générics entre temps ce qui complique l'affaire au niveau du moteur d'inférence de types.

  8. #8
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par cinemania Voir le message
    Cependant utiliser les listes génériques ne règlera pas son problème de cast. En effet ...
    List<object> oList = new List<object>();
    List<int> iList = (List<int>)oList;
    n'est pas possible non plus, on en reviens au même problème, c'est même encore pire ici car tu es passé par le générics entre temps ce qui complique l'affaire au niveau du moteur d'inférence de types.
    Ah si, justement. Dans ce cas tu certain que le contenu de tes listes est du bon type. Et à ce moment, ceci fonctionnera sans peine:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    List<object> objectList = new List<object>();
     
                for (int i = 0; i < 10; i++)
                {
                    objectList.Add(i);
                }
     
                List<int> intList = objectList.ConvertAll<int>(delegate(object o) { return (int) o; });

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    Suis complètement d'accord avec toi, j'utilise massivement les génériques. Si besoin pas de problème j'utiliserai le convertAll et une méthode anonyme pour faire la conversion comme tu l'as indiqué.

    Ce qui me gêne ce n'est pas tant de le faire, mais que je ne m'en étais jamais aperçu jusqu'à aujourd'hui et que j'aurai bien dit que le code suivant était valide

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    object[] oIntTab = new object[]{1};
     int[] jIntTab = (int[])oIntTab;

    On en apprend tous les jours
    En tout cas merci de m'avoir supporté!

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    pfff...décidemment ça me travaille

    Parce que ce code compile lui...il va planter mais il compile

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public static List<T> ConvertArrayListToList<T>( ArrayList p_oList )
    {
         return new List<T>( p_oList.ToArray() as T[] );
    }

  11. #11
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par karlus Voir le message
    On en apprend tous les jours
    En tout cas merci de m'avoir supporté!
    De rien, en cherchant j'apprend aussi donc tous les problèmes un peu plus avancé m'intéresse!

  12. #12
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par karlus Voir le message
    pfff...décidemment ça me travaille

    Parce que ce code compile lui...il va planter mais il compile

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public static List<T> ConvertArrayListToList<T>( ArrayList p_oList )
    {
         return new List<T>( p_oList.ToArray() as T[] );
    }
    Je pense qu'ArrayList est un type qui doit être bannit! :-)

  13. #13
    Membre éprouvé Avatar de Onlava
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2007
    Messages : 92
    Par défaut
    Sinon ya aussi ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ArrayList array;
    int[] liste = (int[]) array.ToArray(typeof(int));
    Je pense qu'ArrayList est un type qui doit être bannit! :-)
    Totalement d'accord avec toi

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    Je pense aussi que ArrayList devrait etre banni.

    neptune, oui la conversion marche avec ConvertAll mais pas sans

    Ensuite dans son dernier cas sa plante car il essaie de faire une conversion avec as qui retournera null car les types sont pas compatibles.
    (en plus as est moins tolérant que le cast, et souvent le as marche pas toujours avec les conversions même lorsqu'on les a défini soit meme comme explicite : public static explicit operator string(Machin obj) enfin moi je sais que dans mon projet à chaque fois me renvoyé null alors qu'un cast sauvage marchait très bien donc

  15. #15
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Citation Envoyé par Onlava Voir le message
    Sinon ya aussi ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ArrayList array;
    int[] liste = (int[]) array.ToArray(typeof(int));
    Tiens! Je n'y avait pas pensé et j'ai cherché la petite bête plus loin que cela. A nouveau, ne fonctionnera que si tous les objets de la liste sont de type "castable" vers int.

  16. #16
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    banni, banni...C'est peut être un peu fort non. Toujours privilégier le générique ok mais parfois avec les problématique d'inférence de type et de covariance qu'à justemment mentionné cinemania on est parfois un peu coincé...

  17. #17
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Karlus, à voir cas particulier. Si tu en as, ca m'intéresse. Mais de toute mon expérience de dévelopeur, je n'ai jamais eu à utiliser une liste "fourre-tout" et toujours priviligié des listes typées. Trouver un bug lié à ce type de liste est un casse-tête parfois monstrueux.

  18. #18
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    moi quand j'ai des listes fourre tout j'utilise des generics avec object

    je peux pas me tromper cela dit, c'est l'ancêtre de tout donc
    mais bon mes cas de listes fourre tout sont plutot des trucs bien précis comme des dictionnaires de stockage de définition de contextes et autres choses amusantes.

    sinon il est vrai qu'en règle général, on a plus souvent recours à des listes qui devraient être typées (d'où les generics) que le contraire.

    En plus l'usage de liste non typées pose des problèmes c'est vrai, pour le debogage, à moins de savoir exactement ce que tu es suceptible de manipuler, tu passe plus de temps à courrir après des bugs "à la con" qu'autre chose. Et moi quand je stocke de tout en vrac, je verifie le type de ce que je récupère... bon cela dit mon projet utilise allégrement la Reflexion donc...

  19. #19
    Membre expérimenté Avatar de fred777888999
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 250
    Par défaut
    On ne peux pas caster un object[] en int[] simplement parceque le type de base (pointeur sur un tableau) est le meme dans les deux cas. Quand a caster chacun des elements individuellement c'est une autre paire de manches. Maintenant rien ne t'empeche de caster un element au moment de son utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    object[] array = new objet[] {1, 2, 3, 4, "toto", "titi" };
    int val = ((int)(oject[1]));
    est tout a fait valide.

  20. #20
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 109
    Par défaut
    Un cas particulier...Avec l'héritage ça ne semble pas toujours évident. Par exemple :

    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
    public class Parent{}
     
        public class Fille : Parent { }
     
        public class Test
        {
            List<Parent> m_oListe = null;
     
            public List<Parent> Liste
            {
                get { return m_oListe; }
                set { m_oListe = value; }
            }
     
            public List<T> GetListGenerique<T>() where T : Parent
            {
               .....
            }
        }
    L'accesseur "Liste" renvoi une collection d'objet parent mais comment écrire un accesseur pour obtenir une Liste du type fils. ( Sans recopier, caster les références ect... )

Discussions similaires

  1. [JSON] Problème de Cast Array en String
    Par helter_skelter dans le forum Format d'échange (XML, JSON...)
    Réponses: 0
    Dernier message: 21/10/2009, 12h02
  2. TStringList en array of string
    Par JediKerian dans le forum Langage
    Réponses: 2
    Dernier message: 20/03/2003, 15h37
  3. Réponses: 2
    Dernier message: 23/02/2003, 00h49
  4. traduction en delphi "reinterpreted cast"
    Par Chupakabra dans le forum Langage
    Réponses: 3
    Dernier message: 13/02/2003, 15h49
  5. passage en paramètre d'un array dynamique 2D
    Par Guigui_ dans le forum Langage
    Réponses: 4
    Dernier message: 27/11/2002, 19h47

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