惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

博客园 - dudu

.NET CQRS 的实现中引入 ReadOnlyRepository 初试 .NET CQRS 开源库 LiteBus 什么是 Agentic ? 初试 Microsoft Agent Framework 初识 Microsoft Agent Framework:一句话介绍 ASP.NET Core 中读取 UserAgent 的正确姿势 记录一下对 ASP.NET Core Middleware 进行单元测试的代码 用 Angular Signal Inputs 完成一个组件的重构 量子网络操作系统 QNodeOS 资料收集 Kubernetes 集群上部署 Open WebUI 在 Kubernetes 集群的 GPU 节点上部署 Ollama 尝试在 Kubernetes 集群上用阿里云 GPU 实例部署 Ollama + DeekSeek-R1 阿里云 GPU 实例云服务器本地部署 DeepSeek R1 尝试使用阿里云计算巢部署 DeepSeek-R1 Angular 中依赖注入问题造成 Observable 订阅不更新 园子博客后台 Angular 升级:手工迁移至 Standalone Component Angular 中使用 ChildContent 记录 园子博客后台升级至 angular 19 后 eslint 9 迁移记录 学习大模型(LLM)的英文好文收集
C# 实现通用的 IdEqualityComparer
dudu · 2025-05-24 · via 博客园 - dudu

这是昨天在园子博客后台开发中遇到的一次代码重构。

两个列表进行 union

posts = [.. pinnedPosts.Union(posts, new IdEqualityComparer())];

需要自己实现一个 EqualityComparer,基于 Id 字段进行进行比较,默认基于对象引用进行比较,不是我们期望的。

IdEqualityComparer 的实现如下

internal class IdEqualityComparer : IEqualityComparer<BlogPost>
{
    public bool Equals(BlogPostModel x, BlogPostModel y)
    {
        return ReferenceEquals(x, y) || (x is not null && y is not null && x.Id == y.Id);
    }

    public int GetHashCode(BlogPostModel obj)
    {
        return obj is null ? 0 : obj.Id.GetHashCode();
    }
}

上面的实现虽然可以工作,但将 IdEqualityComparer 与具体比较的对象类型绑定了,每个被比较的对象都需要实现自己的 IdEqualityComparer,太啰嗦了。

重构实现一个通用的 IdEqualityComparer 是必须的。

泛型可以解决与具体对象类型绑定的问题,但是仅有泛型还不够,因为需要比较 Id 字段,也就是被比较的对象必须要有 Id 字段,这可以通过引入一个接口解决。

public interface IIdentifiable<T>
{
    T Id { get; set; }
}

最后重构出来的通用 IdEqualityComparer 实现

public class IdEqualityComparer<TComparee, TId> : IEqualityComparer<TComparee>
    where TComparee : IIdentifiable<TId>
{
    public bool Equals(TComparee? x, TComparee? y)
    {
        return ReferenceEquals(x, y) ||
            (x is not null && y is not null &&
            (x is IIdentifiable<TId> xx) && (y is IIdentifiable<TId> yy) &&
            xx.Id is not null && yy.Id is not null &&
            xx.Id.Equals(yy.Id));
    }

    public int GetHashCode(TComparee obj)
    {
        if (obj is null)
            return 0;

        if (obj is IIdentifiable<TId> x && x.Id is not null)
        {
            return x.Id.GetHashCode();
        }

        return obj.GetHashCode();
    }
}

重构完成。

参考: