有没有更好的方法来为具有大量字段的对象实现 Equals?

发布于 2024-08-13 14:15:54 字数 953 浏览 2 评论 0原文

另请参阅如何快速查看数据是否存在 传递两个对象相等 C# 中的属性?

我有很多数据传输对象 (DTO),每个对象都包含很多简单字段。我需要对所有这些实现 Equals(这样我就可以编写一些单元测试来传输它们 var WCF)。

我使用的代码是:

public override bool Equals(object rhs)
{

    RequestArguments other = rhs as RequestArguments;

    return
       other != null && 
       other.m_RequestId.Equals(RequestId) && 
       other.m_Type.Equals(m_Type) && 
       other.m_Parameters.Equals(m_Parameters) && 
       other.m_user.Equals(m_user);
}

一定有更好的方法!... (列出所有字段实际上是在询问错误和维护问题)

例如,我们有 Object. MemberwiseClone() 来帮助解决 Cloning() 的情况,但我找不到任何可以帮助 Equals 的东西。 我们完全信任地运行,因此基于反射的解决方案是一个答案,但我不想重新发明轮子。

(抱歉,我们不从特定于域的语言生成 DTO,否则这种事情会很容易!而且我无法更改构建系统以添加另一个步骤)

see also Hows to quick check if data
transfer two objects have equal
properties in C#?

I have lot of Data Transfer Objects (DTO) that each contains lots of simple fields. I need to implement Equals on all of them (so I can write some unit tests off transporting them var WCF).

The code I am using is:

public override bool Equals(object rhs)
{

    RequestArguments other = rhs as RequestArguments;

    return
       other != null && 
       other.m_RequestId.Equals(RequestId) && 
       other.m_Type.Equals(m_Type) && 
       other.m_Parameters.Equals(m_Parameters) && 
       other.m_user.Equals(m_user);
}

There must be a better way!... (listing all the fields is rather asking for errors and maintenance problems)

E.g. we have Object. MemberwiseClone() to help with the Cloning() case, but I cannot find anything to help with Equals.
We are running in full trust so a reflection based solution is one answer, but I rather not reinvent the wheel.

(Sorry we don’t generate the DTO from a domain-specific language otherwise this sort of thing would be easy! Also I am not able to change the build system to add another step)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

素衣风尘叹 2024-08-20 14:15:54

有趣的是,你应该问,我最近发布了一些代码来做到这一点。查看我的 MemberwiseEqualityComparer 看看它是否符合您的需求。

它真的很容易使用而且非常高效。它使用 IL-emit 在第一次运行时生成整个 Equals 和 GetHashCode 函数(每个使用的类型一次)。它将使用该类型的默认相等比较器 (EqualityComparer.Default) 比较给定对象的每个字段(私有或公共)。我们已经在生产中使用它一段时间了,它看起来很稳定,但我不会留下任何保证 =)

它会处理所有那些在你滚动自己的 equals 方法时很少想到的令人讨厌的边缘情况(即,你不能将你自己的对象与 null 进行比较,除非你首先将它装箱在一个对象中并且解决了更多与 null 相关的问题)。

我一直想写一篇关于它的博客文章,但还没有抽出时间。该代码有点未记录,但如果您喜欢它,我可以对其进行一些清理。

public override int GetHashCode()
{
    return MemberwiseEqualityComparer<Foo>.Default.GetHashCode(this);
}

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    return Equals(obj as Foo);
}

public override bool Equals(Foo other)
{
    return MemberwiseEqualityComparer<Foo>.Default.Equals(this, other);
}

MemberwiseEqualityComparer 是根据 MIT 许可证 发布的,这意味着您几乎可以用它做任何您想做的事情,包括在专有解决方案中使用它,而无需稍微改变您的许可。

Funny you should ask, I recently published some code for doing exactly that. Check out my MemberwiseEqualityComparer to see if it fits your needs.

It's really easy to use and quite efficient too. It uses IL-emit to generate the entire Equals and GetHashCode function on the first run (once for each type used). It will compare each field (private or public) of the given object using the default equality comparer for that type (EqualityComparer.Default). We've been using it in production for a while and it seems stable but I'll leave no guarantees =)

It takes care of all those pescy edge-cases that you rarely think of when you're rolling your own equals method (ie, you can't comparer your own object with null unless you've boxed it in an object first and lot's off more null-related issues).

I've been meaning to write a blog post about it but haven't gotten around to it yet. The code is a bit undocumented but if you like it I could clean it up a bit.

public override int GetHashCode()
{
    return MemberwiseEqualityComparer<Foo>.Default.GetHashCode(this);
}

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    return Equals(obj as Foo);
}

public override bool Equals(Foo other)
{
    return MemberwiseEqualityComparer<Foo>.Default.Equals(this, other);
}

The MemberwiseEqualityComparer is released under the MIT license meaining you can do pretty much whatever you want with it, including using it in proprietary solutions without changing you licensing a bit.

花伊自在美 2024-08-20 14:15:54

一种选择是使用反射来获取所有可用字段,然后在所需对象上获取并比较它们的值。这将为您提供一个通用的解决方案,但您需要做相当多的工作,可能使用哈希值(正如亚历克斯建议的那样)是一个更干净的解决方案。

编辑:这是一个使用反射比较对象的简单示例,它查看属性而不是字段,但您明白了:http://www.willasrari.com/blog/use-systemreflection-for-comparing-custom-objects/000257.aspx

An option is to use reflection to get all the available fields and then get and compare their values on the desired objects. This would give you a generic solution but you would have quite a work to do, probably using hashes as Alex suggests is a cleaner solution.

EDIT: Here is a simple example of comparing objects using reflection, it looks at properties instead of fields but you get the idea: http://www.willasrari.com/blog/use-systemreflection-for-comparing-custom-objects/000257.aspx

过去的过去 2024-08-20 14:15:54

您可以有一个对象哈希的概念 - 每当对象发生更改时,您就需要付出更新哈希的代价(其中哈希实际上是所有串联属性的哈希)。然后,如果你有一堆很少改变的对象,那么比较它们真的很便宜。当然,代价是在对象编辑时支付的。

You can have a concept of an object hash - whenever an object changes, you pay the price of updating the hash (where the hash is literally a hash of all concatenated properties). Then, if you have a bunch of objects that rarely change, it's really cheap to compare them. The price, of course, is then paid at object editing time.

情深已缘浅 2024-08-20 14:15:54

编辑:抱歉,我没有注意到您要求进行序列化测试。所以这个方法肯定不适合你。


还有另一种“肮脏”的方式。如果您的对象无论如何都是可序列化的,您可以序列化它们并比较结果流。

这相当慢,但应该非常可靠并且易于实现。

有时我们这样做是为了检查是否有人更改了编辑器中的任何数据。

Edit: sorry, I didn't notice that you are asking for serialization testing. So this approach definitely doesn't work for you.


There is another "dirty" way. If your object is serializable anyway, you can serialize them and compare the resulting streams.

This is rather slow, but should be quite reliable and easy to implement.

We are doing this sometimes to check if someone changed any data in an editor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文