c#比较两个对象模型中的数据

DrL*_*zer 9 c# comparison serialization

我有一个对话框,当它产生时,它会被对象模型中的数据填充.此时,数据被复制并存储在"备份"对象模型中.当用户完成更改并单击"确定"以关闭对话框时,我需要一种快速方法来比较备份对象模型和实时模型 - 如果有任何更改,我可以为用户创建一个新的撤消状态.

如果可能的话,我不想为对象模型中的每个类编写比较函数.

如果我将两个对象模型序列化并且它们相同但存储在不同的内存位置它们是否相等?是否存在比较两个序列化对象模型的简单方法?

DrL*_*zer 11

我没有使用哈希字符串,但只是一个直接的二进制序列化工作奇迹.当对话框打开时序列化对象模型.

BinaryFormatter formatter = new BinaryFormatter();
m_backupStream = new MemoryStream();
formatter.Serialize(m_backupStream,m_objectModel);
Run Code Online (Sandbox Code Playgroud)

然后,如果用户使用可用控件(或不使用)添加到对象模型.当对话框关闭时,您可以使用新的序列化与原始序列化进行比较 - 这对我来说是我如何决定是否需要撤消状态.

BinaryFormatter formatter = new BinaryFormatter();
MemoryStream liveStream = new MemoryStream();
formatter.Serialize(liveStream,m_objectModel);
byte[] streamOneBytes = liveStream.ToArray();
byte[] streamTwoBytes = m_backupStream.ToArray();
if(!CompareArrays(streamOneBytes, streamTwoBytes))
    AddUndoState();
Run Code Online (Sandbox Code Playgroud)

并且比较数组函数可以满足任何人的需要 - 不是比较两个数组的最佳方法.

private bool CompareArrays(byte[] a, byte[] b)
{
    if (a.Length != b.Length)
       return false;

    for (int i = 0; i < a.Length;i++)
    {
       if (a[i] != b[i])
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*kel 6

我想说最好的方法是在你的模型中的所有类上实现相等运算符(如果你要进行比较,这通常是一个好主意).

class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
    public ICollection<Chapter> Chapters { get; set; }

    public bool Equals(Book other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.Title, Title) && Equals(other.Author, Author) && Equals(other.Chapters, Chapters);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Book)) return false;
        return Equals((Book) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int result = (Title != null ? Title.GetHashCode() : 0);
            result = (result*397) ^ (Author != null ? Author.GetHashCode() : 0);
            result = (result*397) ^ (Chapters != null ? Chapters.GetHashCode() : 0);
            return result;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此片段由ReSharper自动生成,但您可以将其作为基础.基本上,您必须使用自定义比较逻辑扩展非重写Equals方法.

例如,您可能希望使用Linq扩展中的SequenceEquals来检查章节集合是否按顺序相同.

比较两本书现在就像说:

Book book1 = new Book();
Book book2 = new Book();

book1.Title = "A book!";
book2.Title = "A book!";

bool equality = book1.Equals(book2); // returns true

book2.Title = "A different Title";
equality = book1.Equals(book2); // returns false
Run Code Online (Sandbox Code Playgroud)

请记住,还有另一种实现相等的方法:System.IEquatable,它由System.Collections命名空间中的各个类用于确定相等性.

我会说检查一下,你就行了!