2009-06-11 4 views
5

Я не ищу сравнение двух структур, которые возвращают bool, мне интересно, есть ли способ получить, какие поля двух структур (одна и та же структура, но, возможно, разные значения) разные. В основном я хочу более простой способ сделать следующее:Сравнение двух значений structs в 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()); 
    } 
} 

Я интересно, если есть способ сделать это с помощью сериализации какого-то, или, если это единственный способ реально увидеть, какие значения были изменены , Даже если есть лучший способ реализовать функцию Compare, я бы тоже принял это.

+0

Проверьте мое решение linq. Его действительно мало. – johnnycrash

ответ

10

Это можно сделать, используя Reflection. Проверьте на FieldInfo и PropertyInfo примеры.

MSDN пример (модифицированный бит):

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 - Правильный ответ – Dario

+0

Есть ли пример того, как получить фактические данные? Похоже, это только для полей/свойств класса, или вы просто предлагаете лучшую реализацию метода Compare? – SwDevMan81

+1

Как вы сказали, если вы хотите узнать, какие поля * разные, тогда вам нужно вернуть какой-то список (например, список ). Но, может быть, вы могли бы описать свою цель более подробно, чтобы мы могли предложить лучшее решение? Например, если это был класс вместо структуры, вы могли бы рассмотреть возможность внедрения интерфейса INotifyPropertyChanged и запуска события каждый раз, когда изменяется свойство - таким образом вам не нужно будет каждый раз проверять все поля. Все зависит от вашей фактической цели. – Groo

1

Я не могу комментировать еще, поэтому в ответ на SwDevMan81 наверху там немного^

Если вы хотите, значение и у вас есть FieldInfo ...

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

Также

GetFields() возвращает переменные-члены. Флаги контролируют, если вы хотите, чтобы публичные/частные/статические и т. Д. Члены.

GetProperties() возвращает свойства.

0

Итак, используя информацию для сообщений народов, мы имели бы новый сравнить метод, который выглядит следующим образом:

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; 
} 

Это, кажется, значительно уменьшить размер функции сравнения, но я до сих пор все класс Diffs и дополнительный код. Есть ли более простой способ, чем это?

+0

Ваш вопрос не достаточно конкретный, чтобы избавиться от класса diff, так как наше понимание результата, который вы ищете, представляет собой набор таких объектов. –

+0

Вопрос задает вопрос о том, есть ли способ.В конце я упоминаю, что я соглашусь на лучшую реализацию Compare, если это все, что было возможно. – SwDevMan81

+0

Просто добавьте это в свой вопрос, вместо того, чтобы добавлять неответ. – 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

К сожалению, я не могу использовать Linq – SwDevMan81

Смежные вопросы