Swift中仅在泛型符合Equatable时比较的实现方案
解决方案:移除@propertyWrapper的Equatable约束并支持条件相等性检查
问题核心
直接将T转为any Equatable后无法用!=比较,因为Equatable协议的==要求左右操作数为同一具体类型,而any Equatable是存在类型,编译器无法保证类型匹配。
正确实现代码
@propertyWrapper struct Enhanced<T> { private var value: T var wrappedValue: T { get { value } set { performUpdate(with: newValue) } } init(wrappedValue: T) { self.value = wrappedValue } mutating func set(_ newValue: T) { performUpdate(with: newValue) } // 统一处理更新逻辑:仅当值变化(或类型不支持Equatable)时执行操作 private mutating func performUpdate(with newValue: T) { let shouldUpdate: Bool // 判断当前值是否支持Equatable if let oldEquatable = value as? any Equatable, let newEquatable = newValue as? any Equatable { // 类型安全的相等性检查 shouldUpdate = !oldEquatable.isEqual(to: newEquatable) } else { // 不支持Equatable时直接更新 shouldUpdate = true } if shouldUpdate { // 在这里执行你的额外操作 value = newValue } } } // 给Equatable添加扩展,提供类型擦除后的相等性判断 extension Equatable { fileprivate func isEqual(to other: any Equatable) -> Bool { // 先尝试将other转为当前类型,再比较 guard let other = other as? Self else { return false } return self == other } }
实现说明
- 移除泛型约束:将
Enhanced<T: Equatable>改为Enhanced<T>,支持任意类型的包装。 - 统一更新逻辑:用
performUpdate(with:)方法封装判断和操作,避免重复代码。 - 类型安全比较:通过
Equatable的扩展方法isEqual(to:),先将other转为当前具体类型Self,再执行==比较,彻底解决any Equatable无法直接比较的问题。 - 兼容非Equatable类型:如果类型不支持
Equatable,直接执行更新操作(可根据需求调整逻辑,比如强制更新或做其他处理)。
为什么原来的尝试会报错
any Equatable是“存在类型”,仅表示该值符合Equatable协议,但编译器无法确定两个any Equatable实例是否属于同一具体类型。而Equatable的==运算符要求左右操作数必须是同一类型,因此直接使用!=会触发编译错误。
内容的提问来源于stack exchange,提问作者ev0
相关产品推荐
相关产品推荐

