You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NUnit比较字典中嵌套的HashSet类型集合?

解决方案

问题原因

NUnit默认的嵌套集合相等比较仅对顶层Dictionary做了无序适配,嵌套的HashSet会被当作普通IEnumerable按迭代顺序逐项比对,所以元素插入顺序不同时会触发断言失败,不符合HashSet的无序语义。

推荐实现方案

方案1:NUnit 3+ 按类型指定嵌套比较器(推荐)

NUnit的Is.EqualTo支持针对嵌套层级的指定类型注册自定义比较器,无需手动遍历集合:

// 字符串类型HashSet场景示例
var setComparer = HashSet<string>.CreateSetComparer();
Assert.That(a2, Is.EqualTo(a1)
    .Using<HashSet<string>>(setComparer));

针对你提到的控制流图业务场景(Dictionary<BasicBlock, HashSet<BasicBlock>>),如果BasicBlock需要自定义相等规则,可以先实现对应比较器再注册:

// 自定义BasicBlock相等比较器(默认Equals符合业务要求可跳过该步骤)
public class BasicBlockComparer : IEqualityComparer<BasicBlock>
{
    public bool Equals(BasicBlock x, BasicBlock y) => x?.BlockId == y?.BlockId;
    public int GetHashCode(BasicBlock obj) => obj?.BlockId ?? 0;
}

// 断言写法
var bbComparer = new BasicBlockComparer();
var cfgSetComparer = HashSet<BasicBlock>.CreateSetComparer(bbComparer);

Assert.That(actualCfgEdges, Is.EqualTo(expectedCfgEdges)
    // 可选:如果Dictionary的键BasicBlock需要自定义比较则添加该行
    .Using<BasicBlock>(bbComparer)
    // 指定HashSet<BasicBlock>类型使用专用集合比较器
    .Using<HashSet<BasicBlock>>(cfgSetComparer));

方案2:手动遍历逐对比较(兼容性更好)

如果使用的NUnit版本不支持按类型注册嵌套比较器,可以手动分两步比较,逻辑更直观:

// 1. 先校验两个字典的键完全匹配
Assert.That(actual.Keys, Is.EquivalentTo(expected.Keys));
// 2. 逐键比较对应的HashSet(Is.EquivalentTo默认无视集合顺序)
foreach (var key in expected.Keys)
{
    Assert.That(actual[key], Is.EquivalentTo(expected[key]));
}

内容的提问来源于stack exchange,提问作者Sweeper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:45:03