我正在实现一个不可变字典的特例,为了方便实现IEnumerable<KeyValuePair<Foo, Bar>>
。通常修改字典的操作应该返回一个新实例。
到目前为止一切顺利。但是当我尝试为该类编写一个流畅的单元测试时,我发现我尝试过的两个流畅的断言库(Should和Fluent Assertions)都不支持NotBeSameAs()
对实现IEnumerable
的对象的操作 - 除非您先将它们转换为Object
。
当我第一次碰到这个时,我认为它只是框架中的一个洞,但是当我看到Fluent Assertions有同样的洞时,它让我觉得(因为我是一个相对较新的人)到C#)我可能会遗漏一些关于C#集合的概念 - 我提交问题时应该implied as much的作者。
显然还有其他方法可以对此进行测试 - 转换为Object
并使用NotBeSameAs()
,只需使用Object.ReferenceEquals
,无论如何 - 但如果有充分理由不这样做,我就是我想知道那是什么。
答案 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/