Swiftで以下のコードはコンパイルエラーになります。
Any型がEquatableに準拠していないというのが理由です。
let dict1: [String: Any] = ["foo": "bar"]
let dict2: [String: Any] = ["foo": "bar"]
print(dict1 == dict2) // Protocol 'Any' as a type cannot conform to 'Equatable'
そこで、以下のように[String: Any]をNSDictionaryにキャストして比較します。
こうするとコンパイルすることができ、結果はtrue
になります。
※この方法では正しい比較ができないケースがあります。次項を参照してください
let dict1: [String: Any] = ["foo": "bar"]
let dict2: [String: Any] = ["foo": "bar"]
print(dict1 as NSDictionary == dict2 as NSDictionary) // true
SwiftではDictionaryとNSDictionaryをシームレスに相互変換することができます。
そして、NSDictionaryはNSObjectのサブクラスであるため、Equatableに準拠しています。
これによって上記の比較が可能になります。
2023/1/6追記
以下の例は一見true
になりそうですが、結果はfalse
になります。
struct Bar: Equatable {
let bar: Int
}
let dict1: [String: Any] = ["foo": Bar(bar: 1)]
let dict2: [String: Any] = ["foo": Bar(bar: 1)]
print(dict1 as NSDictionary == dict2 as NSDictionary) // false
BarをHashableに準拠させるとtrue
になります。
struct Bar: Hashable {
let bar: Int
}
let dict1: [String: Any] = ["foo": Bar(bar: 1)]
let dict2: [String: Any] = ["foo": Bar(bar: 1)]
print(dict1 as NSDictionary == dict2 as NSDictionary) // true
NSDictionary同士の比較はNSObjectProtocolのisEqual(_:)メソッドを使用しています。
このメソッドは2つのオブジェクトのハッシュ値が同じである場合にtrue
を返すようになっています。
Hashableに準拠させることでハッシュの比較が正しくできるようになり、期待通りの結果が得られるようになるのだと思います。
参考