在适当位置改变值类型关联值

时间:2018-01-18 04:37:17

标签: swift enums pass-by-reference value-type

是否可以在Swift中改变枚举关联值,这是一种值类型?如果是,怎么样?

struct S { 
    var a = 1 
}

enum E { 
    case s(S) 
}

var e = E.s(S())
// the goal is to make e hold s with a = 2
// overwriting e is not allowed

if case var .s(s) = e { 
   // s is a copy at this point
   // I want to mutate e in-place
   s.a = 2 
} 

注意:似乎有可能,至少Optional枚举s?.a = 2变异Optional<S>

用例:

我正在Codable周围写一个小包装器,以便在字典和对象之间轻松映射值。我有一个MappingContext,可以是encodedecode。鉴于KeyedEncodingContainer在编码时具有变异功能,我希望此包装器的用户避免重新分配值,并直接改变相关值。

我打开了swift stdlib代码,该函数甚至没有改变结构,但标记为变异。不知道为什么,但我现在可以没有问题的副本,但重新分配是一个可接受的解决方案,只是想确保我没有遗漏任何明显的。

typealias EncodeContainer = KeyedEncodingContainer<JsonCodingKey>
typealias DecodeContainer = KeyedDecodingContainer<JsonCodingKey>


public enum CodingMode {
    case encode(EncodeContainer)
    case decode(DecodeContainer)
}

1 个答案:

答案 0 :(得分:1)

在不覆盖枚举本身的情况下,无法更改枚举关联值;如果将S声明为class,那么这是一项非常简单的任务。

无论如何,我做了一些我在这里报告的实验:

1)基于withUnsafeMutablePointer

var e = E.s(S(a: 1))
withUnsafeMutablePointer(to: &e, {
   $0.pointee = E.s(S(a: 2))
})
print(e)

2)声明变异func隐式覆盖枚举

struct S {
   var a = 1
}

enum E {
   case s(S)
   mutating func setS(val:S) { self = E.s(val) }
}

var e = E.s(S(a: 1))
e.setS(val: S(a: 2))
print(2)

3)如果Sclass

class S:CustomDebugStringConvertible {
   var a = 1
   var debugDescription: String { return "\(a)" }
}

enum E {
   case s(S)
}

let e = E.s(S())
if case let .s(s) = e {
   s.a = 2
}
print(e)