在C#中测试参照平等的通用集合是一个愚蠢的想法吗?

时间:2013-03-13 14:53:13

标签: c# collections equality fluent-assertions

我正在实现一个不可变字典的特例,为了方便实现IEnumerable<KeyValuePair<Foo, Bar>>。通常修改字典的操作应该返回一个新实例。

到目前为止一切顺利。但是当我尝试为该类编写一个流畅的单元测试时,我发现我尝试过的两个流畅的断言库(ShouldFluent Assertions)都不支持NotBeSameAs()对实现IEnumerable的对象的操作 - 除非您先将它们转换为Object

当我第一次碰到这个时,我认为它只是框架中的一个洞,但是当我看到Fluent Assertions有同样的洞时,它让我觉得(因为我是一个相对较新的人)到C#)我可能会遗漏一些关于C#集合的概念 - 我提交问题时应该implied as much的作者。

显然还有其他方法可以对此进行测试 - 转换为Object并使用NotBeSameAs(),只需使用Object.ReferenceEquals,无论如何 - 但如果有充分理由不这样做,我就是我想知道那是什么。

2 个答案:

答案 0 :(得分:1)

IEnumerable<T>不一定是真实的对象。 IEnumerable<T>保证您可以枚举其状态。在简单的情况下,您有一个容器类,如List<T>已经实现。然后你可以比较两个列表的地址。但是,您的IEnumerable<T>也可能指向一系列命令,这些命令将在您枚举后执行。基本上是状态机:

public IEnumerable<int> GetInts()
{
    yield return 10;
    yield return 20;
    yield return 30;
}

如果将其保存在变量中,则没有可比较的对象(一切都是对象,所以你做...但它没有意义):

var x = GetInts();

您的比较仅适用于物化(.ToList().ToArray())IEnumerables,因为已对这些状态机进行了评估,并将其结果保存到集合中。所以是的,这个库实际上是有意义的,如果你知道你已经实现了IEnumerables,你需要通过将它们转换为Object并在“手动”上对该对象调用所需的函数来公开这些知识。 / p>

答案 1 :(得分:1)

另外,Jon Skeet建议看一下2013年2月来自Ted Neward的MSDN文章:

.NET Collections, Part 2: Working with C5

  

不可变(受保护)收藏

     

随着功能概念的兴起   和编程风格,很多重点都转向了不可变数据   和不可变对象,主要是因为不可变对象提供了很多   对并发和并行编程的好处,但也   因为许多开发人员发现不可变对象更容易理解   和理由。因此,该概念的推论遵循这一概念   不可变的集合 - 这个想法无论是否   集合中的对象是不可变的,集合本身就是   已修复且无法更改(添加或删除)中的元素   采集。 (注意:您可以看到不可变集合的预览   发布于NuGet的MSDN基类库(BCL)博客中   bit.ly/12AXD78。)

它描述了使用名为C5的集合善的开源库。 看http://itu.dk/research/c5/