2017-07-08 65 views
0

是否有任何解决方法可以用Optional键创建字典?我知道一个合适的解决方案需要实现条件一致性,但在那之前我有什么选择吗?可选键字典

let dict: [Int?: Int] = [nil: 1] 
// ERROR: type 'Int?' does not conform to protocol 'Hashable' 
+0

你确定你想吗?根据定义,'nil'键表示*无值*,并且类型不能桥接到'NSDictionary',因为Foundation类型仅支持非可选类型作为键**和**值。 – vadian

+0

@vadian是的,我不需要向'NSDictionary'寻宝。这里是我的用例:我在目标C运行库中构建类的层次结构。该字典将类映射到它们的子类的数组。根类有一个“nil”超类,如'class_getSuperclass'所给出的。 – Alexander

+0

@vadian它可以桥接到'NSDictionary',因为'nil'被桥接到'NSNull'。 – Hamish

回答

1

这里有一个解决方法,我发现:创建一个新的HashableOptionalenum

enum HashableOptional<Wrapped: Hashable> { 
    case none 
    case some(Wrapped) 

    public init(_ some: Wrapped) { 
     self = .some(some) 
    } 

    public init(_ optional: Wrapped?) { 
     self = optional.map{ .some($0) } ?? .none 
    } 

    public var value: Wrapped? { 
     switch self { 
      case .none: return nil 
      case .some(let wrapped): return wrapped 
     } 
    } 
} 

extension HashableOptional: Equatable { 
    static func ==(lhs: HashableOptional, rhs: HashableOptional) -> Bool { 
     switch (lhs, rhs) { 
      case (.none, .none): return true 
      case (.some(let a), .some(let b)): return a == b 
      default: return false 
     } 
    } 
} 

extension HashableOptional: Hashable { 
    var hashValue: Int { 
     switch self { 
      case .none: return 0 
      case .some(let wrapped): return wrapped.hashValue 
     } 
    } 
} 

extension HashableOptional: ExpressibleByNilLiteral { 
    public init(nilLiteral:()) { 
     self = .none 
    } 
} 

然后你就可以使用它像这样:

let dict: [HashableOptional<Int>: Int] = [nil: 1] 
+0

个人而言,我只是使包装类型为'struct'暴露了''wrap'''''base'属性,然后在需要访问可选值时只需引用'key.base'。因为'Optional'带有许多无法在包装本身上复制的烘焙语言特性(可选链接,可选绑定,隐式提升,糖模式...),因此IMO在包装器而基础价值提供了更一致的界面。 – Hamish

+0

@Hamish好点。正如你所看到的,我跳过了添加地图和平面地图。我认为访问该值会更容易,我也可以直接存储它。你知道,我很喜欢你如何在没有/某些情况下使用任何类型的条件绑定 – Alexander