2009-06-11 7 views
5

Je ne cherche pas une comparaison de deux structures qui retourne bool, je me demande s'il y a un moyen d'obtenir quels champs de deux structures (la même structure, mais peut-être des valeurs différentes) sont différents. Fondamentalement, je veux une façon plus simple de faire ce qui suit:Comparer les valeurs de deux structures en C#

public class Diff 
{ 
    public String VarName; 
    public object Val1; 
    public object Val2; 

    public Diff(String varName, object val1, object val2) 
    { 
     VarName = varName; 
     Val1 = val1; 
     Val2 = val2; 
    } 

    public override string ToString() 
    { 
     return VarName + " differs with values " + Val1 + " and " + Val2; 
    } 
} 

public struct TestStruct 
{ 
    public int ValueOne; 
    public int ValueTwo; 
    public int ValueThree; 

    public List Compare(TestStruct inTestStruct) 
    { 
     List diffs = new List(); 
     if (ValueOne != inTestStruct.ValueOne) 
     { 
      diffs.Add(new Diff("ValueOne", ValueOne, inTestStruct.ValueOne)); 
     } 
     if (ValueTwo != inTestStruct.ValueTwo) 
     { 
      diffs.Add(new Diff("ValueTwo", ValueTwo, inTestStruct.ValueTwo)); 
     } 
     if (ValueThree != inTestStruct.ValueThree) 
     { 
      diffs.Add(new Diff("ValueThree", ValueThree, inTestStruct.ValueThree)); 
     } 
     return diffs; 
    } 
} 

public CompareStructsExample() 
{ 
    TestStruct t1 = new TestStruct(); 
    t1.ValueOne = 1; 
    t1.ValueTwo = 8; 
    t1.ValueThree = 5; 

    TestStruct t2 = new TestStruct(); 
    t2.ValueOne = 3; 
    t2.ValueTwo = 8; 
    t2.ValueThree = 7; 

    List diffs = t1.Compare(t2); 
    foreach (Diff d in diffs) 
    { 
     System.Console.WriteLine(d.ToString()); 
    } 
} 

Je me demande s'il y a un moyen de le faire avec sérialisation de quelque sorte, ou si cela est le seul moyen de voir réellement quelles valeurs ont changé . Même s'il existe une meilleure façon d'implémenter la fonction de comparaison, je le prendrais aussi.

+0

Vérifiez ma solution linq. C'est vraiment petit. – johnnycrash

Répondre

10

Cela peut être fait en utilisant Reflection. Vérifiez les exemples FieldInfo et PropertyInfo.

exemple MSDN (modifié un peu):

Type myType = typeof(TestStruct); 

    // Get the fields of TestStruct. 
    FieldInfo[] myFieldInfo = 
     myType.GetFields(
      BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 

    Console.WriteLine("\nThe fields of TestStruct are \n"); 

    // Display the field information of TestStruct. 
    for(int i = 0; i < myFieldInfo.Length; i++) 
    { 
     Console.WriteLine("\nName   : {0}", myFieldInfo[i].Name); 
     Console.WriteLine("Declaring Type : {0}", myFieldInfo[i].DeclaringType); 
     Console.WriteLine("IsPublic  : {0}", myFieldInfo[i].IsPublic); 
     Console.WriteLine("MemberType  : {0}", myFieldInfo[i].MemberType); 
     Console.WriteLine("FieldType  : {0}", myFieldInfo[i].FieldType); 
     Console.WriteLine("IsFamily  : {0}", myFieldInfo[i].IsFamily); 
    } 
+0

Yep - Bonne réponse – Dario

+0

Existe-t-il un exemple pour obtenir les données réelles? On dirait que c'est juste pour les champs/propriétés d'une classe, ou suggérez-vous simplement une meilleure implémentation pour la méthode Compare? – SwDevMan81

+1

Comme vous l'avez dit, si vous voulez savoir * quels * champs sont différents, alors vous devez retourner une sorte de liste (Liste , par exemple). Mais peut-être que vous pourriez décrire votre objectif avec plus de détails, afin de nous proposer une meilleure solution? Par exemple, s'il s'agissait d'une classe au lieu de struct, vous pouvez envisager d'implémenter l'interface INotifyPropertyChanged et de déclencher un événement chaque fois qu'une propriété est modifiée. Ainsi, vous n'aurez pas à vérifier tous les champs à chaque fois. Tout dépend de votre objectif réel. – Groo

1

Je ne peux pas ajouter encore de commentaires, donc en réponse à SwDevMan81 au-dessus il y a un peu^

Si vous voulez la valeur et vous avez un FieldInfo ...

object val = myFieldInfo[i].GetValue(Obj); 

en outre,

GetFields() renvoie les variables de membre. Les drapeaux contrôlent si vous voulez des membres public/privé/statique etc.

GetProperties() renvoie les propriétés.

0

Ok, donc en utilisant les informations des messages des peuples, nous aurions une nouvelle comparer méthode qui ressemble à ceci:

public List Compare2(TestStruct inTestStruct) 
{ 
    List diffs = new List(); 

    FieldInfo[] fields = this.GetType().GetFields(); 
    FieldInfo[] fields2 = inTestStruct.GetType().GetFields(); 

    for (int i = 0; i < fields.Length; i++) 
    { 
    object value1 = fields[i].GetValue(this); 
    object value2 = fields2[i].GetValue(inTestStruct); 
    if (!value1.Equals(value2)) 
    { 
     diffs.Add(new Diff(fields[i].Name, value1, value2)); 
    } 
    } 
    return diffs; 
} 

Cela semble réduire considérablement la taille de la fonction de comparaison, mais je dois encore tout la classe Diffs et le code supplémentaire. Y a-t-il un moyen plus simple que cela?

+0

Votre question n'est pas assez spécifique pour se débarrasser de la classe diffs, car notre compréhension du résultat que vous recherchez est un ensemble de tels objets. –

+0

La question demande s'il y a une manière simpilar.A la fin je mentionne que je me contenterais d'une meilleure implémentation de Compare si c'est tout ce qui était possible – SwDevMan81

+0

Ajoutez simplement ceci à votre question au lieu d'ajouter une non-réponse. – TheSoftwareJedi

0

Linq?

public List<string> Compare(TestStruct x, TestStruct y) { 
    return ( 
     from l1 in x.GetType().GetFields() 
     join l2 in y.GetType().GetFields() on l1.Name equals l2.Name 
     where !l1.GetValue(x).Equals(l2.GetValue(y)) 
     select string.Format("{0} {1} {2}", l1.Name, l1.GetValue(x), l2.GetValue(y)) 
    ).ToList(); 
    } 
+0

Malheureusement, je ne peux pas utiliser Linq – SwDevMan81

Questions connexes