以下类型转换会产生哪些不同的运行时成本?
常量的数字广播,例如:
let f = 0.1 as CGFloat
我认为这没有运行时间成本。
运行时值的数字转换,例如:
let f = someDoubleValue as CGFloat
我想这会有非常小的运行时成本。
Upcast ,例如:
let dict: [String: Int] = ...
let anyObj = dict as AnyObject
我希望它的运行时成本为零。
可投降的,例如:
let anyObj: AnyObject = ...
if let str = anyObj as? String { ... }
我希望它的运行时成本与动态类型anyObj
的层次结构中的类数量成比例。
强制向下倾斜,例如:
let anyObj: AnyObject = ...
let str = anyObj as! String
强迫低价的成本可能略低一些?
强制收集广告,例如:
let dates: [AnyObject] = ...
for date in dates as! [NSDate] { ... }
这里会发生什么 - 特别是当dates
来自NSArray
时?此演员的运行时成本是否与其元素的数量成比例?如果我转换为更复杂的集合类型,如[String: [String: [Int]]]
,那么整个集合是否遍历以确保其所有元素和子元素都符合此类演员?
对于前四种情况中的每一种情况,我的断言都是真的吗?
答案 0 :(得分:17)
如果它是明显可铸造的(如数字铸造和向上铸造),则为O(1)(几乎为0):案例1,2,3。
对于其他非收集铸件,显然是O(1):案例4,5。
收集向下转发:
as?
是O(n),因为要急切地执行元素类型检查。NSArray as! [NSDate]
)是O(n),因为要热切地执行元素类型检查。来源:
答案 1 :(得分:0)
只是想补充一下,协议类型转换的运行时成本是惊人的。我试图在反汇编视图中查看它,而只是不了解发生了什么。像这样的一行:
(self as! SomeProtocol).someMethod()
导致保留/释放(涉及内存障碍),然后调用了旧商品objc_msgSend()
(!),但与someMethod()
无关,我想是因为{{1} }或self
是从SomeProtocol
派生的,然后是非常长的函数调用链,其中涉及一些循环。就像我说的那样,我在尝试在反汇编视图中调试这一行代码时失去了耐心。
虽然协议是非常好的抽象,但应在性能关键代码中谨慎使用。