为什么F#的习惯性字典集合(Map<K,V>)需要K类型来实现比较,而C#的Dictionary<K,V>不需要?

问题描述 投票:0回答:1

我知道这个问题和我前段时间问的这个问题很相似。为什么F#的默认集合是排序的,而C#的不是?

但是,我想确认一下,那里给出的原因是否和这种情况一样?而且我想知道是否有一种实现不可变的 Map 在F#中,有谁写的,不那么严格,不需要K来比较?我很乐意用,因为我不那么在乎性能。

dictionary f# hashtable c#-to-f#
1个回答
4
投票

为什么F#的成语字典集合要排序 Map<K,V> 需要类型K来实现比较,而C#的 Dictionary<K,V> 没有?

F# Map<Key, Value> 要求键是可比的,因为map是 以树状结构实现 (你必须根据比较结果决定去哪个子树)。C# Dictionary<Key, Value> 被实现为一个链接列表的桶。你通过键的哈希码得到一个桶,然后迭代列表,直到你(不)找到相等的键。在这两种数据结构中,键都是比较的。唯一不同的是,对于字典的平等比较就足够了。

所以,问题是为什么F# Map明确 比较约束,但C# Dictionary隐性 平等要求?

让我们从C#开始。如果字典有一个叫 IEquatable 关键约束?那么,你会 必须手动实现这个接口 对于每个用作字典键的自定义数据类型。但是如果你想要不同的平等性实现呢?例如,在一些字典中,你希望你的键字符串不区分大小写。当然,你可以通过 IEqualityComparer 的实现来进行键的比较(不仅是与字典的比较,而是在任何需要比较的地方)。但是,如果外部比较器被使用,为什么还要强制要求键比较呢?请注意,如果你不向字典传递任何东西,总会有一个默认比较器被使用。缺省比较器检查 key 是否实现了 IComparable 并使用该实现。

那为什么F#对关键数据类型有一个明确的可比较约束呢?因为这个约束条件 不会强制您手动执行 IComparable 对于每一个用作映射键的自定义数据类型。C#和F#类型系统的一个很大的区别是,F#类型默认是可比较和等价的。F#编译器会生成 IComparable, IComparable<T>IStructuralComparable 实现,除非你明确地用 NoComparison 属性。所以,当你使用F#数据类型时,这个约束并不强制你写任何额外的代码。

使用comparisonequality约束还有一个好处--F#对实现比较或平等的类型有许多预定义的通用操作(=,<,<=,>=,=,max,min)。这使得使用通用comparableequatable类型的代码更加可读。

© www.soinside.com 2019 - 2024. All rights reserved.