在C#中比较两个结构体的值

6

我不是在寻找返回布尔值的两个结构体的比较,而是想知道是否有一种方法可以得到两个结构体(相同的结构,但可能具有不同的值)中哪些字段不同。基本上,我想要一个更简单的方法来执行以下操作:

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"函数的方式,我也会采纳。

看看我的linq解决方案吧,它真的很小。 - johnnycrash
4个回答

10

可以使用反射来完成。请查看FieldInfoPropertyInfo示例。

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

有没有获取实际数据的示例?看起来这只是针对类的字段/属性,或者您只是建议更好的Compare方法实现? - SwDevMan81
1
正如你所说,如果你想知道哪些字段不同,那么你需要返回某种列表(例如List<Diff>)。但也许你可以更详细地描述你的目标,以便我们提出更好的解决方案?例如,如果这是一个类而不是结构体,你可以考虑实现INotifyPropertyChanged接口,并在每次属性更改时触发事件——这样你就不必每次都检查所有字段。这完全取决于你的实际目标。 - vgru
@Groo - 最终目标是比较两个XML文件并显示不同的属性和值。我想XML文件将被序列化为结构并解析出差异。如果结构的值发生更改,我不需要知道(INotifyPropertyChanged)。 - SwDevMan81

1

我还不能添加评论,所以回应一下上面的SwDevMan81 ^

如果你想要这个值并且你有一个FieldInfo...

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

另外,

GetFields() 返回成员变量。标志控制是否需要公共/私有/静态等成员。

GetProperties() 返回属性。


1

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

很遗憾,我不能使用Linq。 - SwDevMan81

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类和额外的代码。还有比这更简单的方法吗?


你的问题不够具体,无法摆脱 diffs 类,因为我们对你所寻找的结果的理解是这样一组对象。 - Frank Schwieterman
问题询问是否有更简单的方法。最后我提到,如果只有这种可能,我会接受更好的Compare实现。 - SwDevMan81
请将此内容添加到您的问题中,而不是添加一个非答案。 - TheSoftwareJedi
@TheSoftwareJedi - 如果这就是答案呢?如果有更好的东西,我可以将其移动到问题中,你对问题有任何实际的输入吗? - SwDevMan81

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接