Сравните значения двух структур в C # - PullRequest
5 голосов
/ 12 июня 2009

Я не ищу сравнения двух структур, которые возвращают bool, мне интересно, есть ли способ узнать, какие поля двух структур (одна структура, но, возможно, разные значения) различны. В основном я хочу более простой способ сделать следующее:

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

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

Ответы [ 4 ]

10 голосов
/ 12 июня 2009

Это можно сделать с помощью 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);
    }
1 голос
/ 12 июня 2009

Я пока не могу добавлять комментарии, поэтому в ответ на SwDevMan81 вверху есть немного ^

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

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

Кроме того,

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

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

0 голосов
/ 17 июня 2009

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 голосов
/ 12 июня 2009

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

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 и дополнительный код. Есть еще более простой способ, чем этот?

...