Compare two structs' values in C#

故事扮演 提交于 2019-12-22 07:49:14

问题


I'm not looking for a comparison of two structs that returns bool, I am wondering if there is a way to get which fields of two structs (the same structure, but maybe different values) are different. Basically I want a simpler way to do the following:

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

I'm wondering if there is a way to do this with serialization of some sort, or if this is the only way to actually see which values have changed. Even if there is a better way to implement the Compare function, I would take that too.


回答1:


It can be done using Reflection. Check for FieldInfo and PropertyInfo examples.

MSDN example (modified a bit):

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



回答2:


I can't add comments yet, so in response to SwDevMan81 up above there a bit ^

If you want the value and you have a FieldInfo...

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

Also,

GetFields() returns member variables. The flags control if you want public/private/static etc members.

GetProperties() returns properties.




回答3:


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



回答4:


Ok, so using the information for peoples posts, we would have a new compare method that looks like this:

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

This seems to significantly reduce the size of the compare function, but I still have all the Diffs class and extra code. Is there a simpler way than this still?



来源:https://stackoverflow.com/questions/983410/compare-two-structs-values-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!