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 :

comparer les valeurs de 2 objets de même type


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 45
    Points : 30
    Points
    30
    Par défaut comparer les valeurs de 2 objets de même type
    Bonjour à tous,

    Je souhaiterais comparer 2 objets de même type (en runtime) par une methode générique qui fonctionnerait avec n'importe quels objets.

    J'ai voulu le développer avec la reflection mais je n'arrive pas à rendre ma méthode recursive (cad boucler sur les sous-objets des objets et ainsi de suite).

    J'obtiens le message
    Target parameter count exception (nombre de parametres incorrect)
    sur la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     //if a public property in the 1rst objedct is different from 
                    //the same public field in the 2nd object
                    //then exit the method
     
                    Console.WriteLine(info.GetValue(object1, null).ToString() + " <===> " + info.GetValue(object2, null).ToString());
    Voici mon code entier :

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
     
    using System;
    using System.Data;
    using System.Configuration;
    using System.IO;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace nameCompareObjects
    {
        public class CompareWithReflection
        {
            public static bool Compare(Object object1, Object object2)
            {
                Type object1Type = object1.GetType();
                Type object2Type = object2.GetType();
     
                //if the types are different then exit the method
                if (!object1Type.Equals(object2Type))
                    return false;
     
                //*********************************************************************************************
                //list of public fields in an object
                System.Reflection.FieldInfo[] fieldInfo = object1Type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
     
                foreach (System.Reflection.FieldInfo info in fieldInfo)
                {
                    //if a public field in the 1rst objedct is different from 
                    //the same public field in the 2nd object
                    //then exit the method
     
                    Console.WriteLine(info.GetValue(object1).ToString() + " <===> " + info.GetValue(object2).ToString());
                    Console.ReadKey();
                    if (!info.GetValue(object1).Equals(info.GetValue(object2)))
                        return false;
     
                    //if the a public field is a class then re-enter the method "compare" recursively
                    if (info.FieldType.IsClass)
                    {
                        bool returned = Compare((Object)info.GetValue(object1), (Object)info.GetValue(object2));
     
                        if (returned == false)
                            return false;
                    }
                }
                //*********************************************************************************************
     
                //*********************************************************************************************
                //list of public properties in an object
                System.Reflection.PropertyInfo[] propertyInfo = object1Type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
     
                foreach (System.Reflection.PropertyInfo info in propertyInfo)
                {
                    //if a public property in the 1rst objedct is different from 
                    //the same public field in the 2nd object
                    //then exit the method
     
                    Console.WriteLine(info.GetValue(object1, null).ToString() + " <===> " + info.GetValue(object2, null).ToString());
     
                    if (!info.GetValue(object1, null).Equals(info.GetValue(object2, null)))
                        return false;
     
                    //if the a public property is a class then re-enter the method "compare" recursively
                    if (info.DeclaringType.IsClass)
                    {
                        bool returned = Compare((Object)info.GetValue(object1, null), (Object)info.GetValue(object2, null));
     
                        if (returned == false)
                            return false;
                    }
     
                }
                Console.WriteLine("true");
                return true;
            }
     
            public static void Main()
            {
                Person person1 = new Person();
                Person person2 = new Person();
     
                person1.FirstName = "Jean";
                person1.LastName = "Dupont";
                person1.Age = 22;
                Car car1 = new Car();
                car1.Brand = "Toyota";
                car1.Model = "Yaris";
                car1.Power = 32;
                person1.Car = car1;
     
                person2.FirstName = "Jean";
                person2.LastName = "Dupont";
                person2.Age = 22;
                Car car2 = new Car();
                car2.Brand = "Toyota";
                car2.Model = "Yaris";
                car2.Power = 32;
                person2.Car = car2;
     
                bool returned = Compare(person1, person2);
     
                Console.WriteLine(returned.ToString());
     
                Console.ReadKey();
            }
     
    }
    }
    Class Car :

    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
     
    using System;
    using System.Data;
    using System.Configuration;
     
    namespace nameCompareObjects
    {
        public class Car
        {
            private string _brand;
            private string _model;
            private int _power;
     
            public string Brand
            {
                get { return this._brand; }
                set { this._brand = value; }
            }
     
            public string Model
            {
                get { return this._model; }
                set { this._model = value; }
            }
            public int Power
            {
                get { return _power; }
                set { _power = value; }
            }
        }
    }
    Classe Person :

    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
     
     
    using System;
    using System.Data;
    using System.Configuration;
     
    namespace nameCompareObjects
    {
        public class Person
        {
            private string _firstName;
            private string _lastName;
            private int _age;
            private Car _car;
     
            public string FirstName
            {
                get { return this._firstName; }
                set { this._firstName = value; }
            }
            public string LastName
            {
                get { return this._lastName; }
                set { this._lastName = value; }
            }
            public int Age
            {
                get { return this._age; }
                set { this._age = value; }
            }
            public Car Car
            {
                get { return this._car; }
                set { this._car = value; }
            }
     
        }
    }

    Quelqu'un aurait-il une idée pour améliorer ce code ?

    Ou y aurait-il une méthode pour comparer en profondeur 2 objets de même type ?

    Merci beaucoup par avance.

    Laurent.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Tu te rendre la vie difficile en voulant passer par la réflexion.
    Pourquoi ne pas tout simplement redéfinir la méthode Equals sur chacune de tes classes ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 45
    Points : 30
    Points
    30
    Par défaut
    h2s84 : merci pour ta réponse.

    En fait je voulais une methode générique sans avoir à taper du code spécifique dans chaque classe...

    Laurent.

  4. #4
    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 : 42
    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
    Points : 39 754
    Points
    39 754
    Par défaut
    Citation Envoyé par laurent12345 Voir le message
    En fait je voulais une methode générique sans avoir à taper du code spécifique dans chaque classe...
    C'est très difficile de faire un code générique "fiable" pour faire ce genre de choses. Juste en jetant un coup d'oeil à ton code, je vois plein de problèmes potentiels que tu ne gères pas. Et il y a un aussi un cas assez compliqué à gérer si tu compares récursivement : les références cycliques. Si tu as un objet A qui fait référence à un objet B, et que B fait également référence à A, la récursion ne se termine jamais et ça finit par planter avec un StackOverflowException...

    De toutes façons, ça n'a pas forcément de sens de comparer des objets en prenant en compte tous ses champs et propriétés. Il vaut mieux écrire du code spécifique en implémentant les méthodes Equals et GetHashCode (tu peux aussi implémenter IEquatable<T>)

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 45
    Points : 30
    Points
    30
    Par défaut
    Merci tomlev pour ta réponse.

    Et bien puisque j'ai eu 2 avis qui me déconseillent de faire un code générique mais plutôt d'implémenter une méthode Equals ou similaire, je crois que je vais revoir mes prétentions à la baisse

    Donc à chaque fois que j'aurai une comparaison d'objets à faire, j'implémenterai une méthode Equals.

    Je voudrais signaler un assembly (KellermanSoftware.CompareNetObjects) qui est freeware mais sans code source et qui marche très bien pour comparer 2 objets en testant avec les 2 classes que j'ai fournies.
    Mais le problème est que je ne maitrise pas grand chose et que je ne sait pas si c'est fiable pour tous les cas.

    Laurent.

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

Discussions similaires

  1. [C#] Comparer les valeurs de deux listes d'objets
    Par pitipilot dans le forum C#
    Réponses: 12
    Dernier message: 08/12/2014, 11h59
  2. Réponses: 0
    Dernier message: 18/04/2013, 21h55
  3. Réponses: 2
    Dernier message: 21/03/2013, 18h38
  4. Réponses: 6
    Dernier message: 04/03/2007, 19h16
  5. comparer les valeurs d'un même tableau
    Par DelphLaga dans le forum Langage
    Réponses: 11
    Dernier message: 19/07/2006, 14h32

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