请考虑以下示例代码:
enum Counter { case value(Int) mutating func add(value: Int) { // part A var orig = self defer { print("[part A] direct defer : ", value, "+", orig, "=", self) } // part B do { var orig = self defer { print("[part B] do block defer: ", value, "+", orig, "=", self) } } if case let .value(prev) = self { self = .value(value + prev) } } } var c = Counter.value(0) c.add(value: 10)
我们有一个简单的计数器枚举,有一个用于存储为Int计数器的情况.该函数在提取的计数器值中add
添加给定value
值self
,然后更新它.
print
延迟语句中有两个s,part A
在函数级别part B
作用域,并且在本do
地块中作用域- 否则,两者都会打印一个日志,其中包含哪些值被添加到什么以及最终输出将是什么.
基于代码,对于两个延迟print
s ,输出应该看起来是相同的; 但是,他们是不同的:
[part B] do block defer: 10 + value(0) = value(0) [part A] direct defer : 10 + value(0) = value(10)
他们为什么不一样?
do
块是否会自我捕获并将其传递给过早推迟,或者是这个预期的设计以及需要注意的问题?
此行为是预期的.
来自语言参考 - 陈述 [强调我的]
推迟声明
延迟语句用于在将程序控制转移到延迟语句出现的范围之外之前执行代码.
因此,当A
defer
您的示例执行时,变异add(value:)
函数已完成其工作,因此增加self
(到10
).虽然B
defer
声明被放置在do
正文中,但是一旦do
将程序控制转移回直接范围,它就被执行add(value:)
.因此,当B
defer
语句执行时,self
尚未发生变异.