Swift开发基础04-枚举
基本用法
1 2 3 4 5 6 7 8 9 10 | enum Direction { case north case south case east case west } enum Direction { case north, south, east, west } |
1 2 3 4 | var dir = Direction.west dir = Direction.east dir = .north print(dir) // north |
1 2 3 4 5 6 7 8 9 10 | switch dir { case .north: print( "north" ) case .south: print( "south" ) case .east: print( "east" ) case .west: print( "west" ) } |
关联值(Associated Values)
有时会将枚举的成员值跟其他类型的关联存储在一起,会非常有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | enum Score { case points(Int) case grade(Character) } var score = Score.points(96) score = .grade( "A" ) switch score { case let .points(i): print(i, "points" ) case let .grade(i): print( "grade" , i) } // grade A |
1 2 3 4 5 6 7 8 9 10 11 12 13 | enum Date { case digit(year: Int, month: Int, day: Int) case string(String) } var date = Date.digit(year: 2011, month: 9, day: 10) date = .string( "2011-09-10" ) switch date { case .digit(let year, let month, let day): print(year, month, day) case let .string(value): print(value) } // 必要时let也可以改为var |
原始值(Raw Values)
枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做:原始值
1 2 3 4 5 6 7 8 9 10 11 | enum PokerSuit : Character { case spade = "♠" case heart = "♥" case diamond = "♦" case club = "♣" } var suit = PokerSuit.spade print(suit) // spade print(suit.rawValue) // ♠ print(PokerSuit.club.rawValue) // ♣ |
1 2 3 4 5 6 7 8 9 10 | enum Grade : String { case perfect = "A" case great = "B" case good = "C" case bad = "D" } print(Grade.perfect.rawValue) // A print(Grade.great.rawValue) // B print(Grade.good.rawValue) // C print(Grade.bad.rawValue) // D |
隐式原始值(Implicitly Assigned Raw Values)
如果枚举的原始值类型是Int、String,Swift会自动分配原始值
1 2 3 4 5 6 7 8 9 10 11 12 | enum Direction : String { case north = "north" case south = "south" case east = "east" case west = "west" } // 等价于 enum Direction : String { case north, south, east, west } print(Direction.north) // north print(Direction.north.rawValue) // north |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | enum Season : Int { case spring, summer, autumn, winter } print(Season.spring.rawValue) // 0 print(Season.summer.rawValue) // 1 print(Season.autumn.rawValue) // 2 print(Season.winter.rawValue) // 3 enum Season : Int { case spring = 1, summer, autumn = 4, winter } print(Season.spring.rawValue) // 1 print(Season.summer.rawValue) // 2 print(Season.autumn.rawValue) // 4 print(Season.winter.rawValue) // 5 |
递归枚举 (indirect)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | indirect enum ArithExpr { case number(Int) case sum(ArithExpr, ArithExpr) case difference(ArithExpr, ArithExpr) } enum ArithExpr { case number(Int) indirect case sum(ArithExpr, ArithExpr) <br> indirect case difference(ArithExpr, ArithExpr) } let five = ArithExpr.number(5) let four = ArithExpr.number(4) let two = ArithExpr.number(2) let sum = ArithExpr.sum(five, four) let difference = ArithExpr.difference(sum, two) |
1 2 3 4 5 6 7 8 9 | func calculate(_ expr: ArithExpr) -> Int { switch expr { case let .number(value): return value case let .sum(left, right): return calculate(left) + calculate(right) case let .difference(left, right): return calculate(left) - calculate(right) } } calculate(difference) |
MemoryLayout
可以使用MemoryLayout获取数据类型占用的内存大小
1 2 3 4 5 6 7 | enum Password { case number(Int, Int, Int, Int) case other } MemoryLayout<Password>.stride // 40, 分配占用的空间大小 MemoryLayout<Password>.size // 33, 实际用到的空间大小 MemoryLayout<Password>.alignment // 8, 对齐参数 |
1 2 3 4 5 | var pwd = Password.number(9, 8, 6, 4) pwd = .other MemoryLayout.stride(ofValue: pwd) // 40 MemoryLayout.size(ofValue: pwd) // 33 MemoryLayout.alignment(ofValue: pwd) // 8 |
窥探枚举的内存
1、枚举有2个case及以上的情况
1 2 3 4 5 6 7 | enum TestEnum { case test1(Int, Int, Int) case test2(Int, Int) case test3(Int) case test4(Bool) case test5 } |
MemoryLayout<TestEnum>.stride // 32, 分配占用的空间大小
MemoryLayout<TestEnum>.size // 25, 实际用到的空间大小
MemoryLayout<TestEnum>.alignment // 8, 对齐参数
通过观察枚举变量e的内存布局:
test1
1 2 3 4 5 6 7 8 9 10 11 | // 1个字节存储成员值 // N个字节存储关联值(N取占用内存最大的关联值),任何一个case的关联值都共用这N个字节 // 共用体 // 小端:高高低低 // 01 00 00 00 00 00 00 00 // 02 00 00 00 00 00 00 00 // 03 00 00 00 00 00 00 00 // 00 // 00 00 00 00 00 00 00 var e = TestEnum.test1(1, 2, 3) |
test2
1 2 3 4 5 6 | // 04 00 00 00 00 00 00 00 // 05 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 01 // 00 00 00 00 00 00 00 e = .test2(4, 5) |
test3
1 2 3 4 5 6 | // 06 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 02 // 00 00 00 00 00 00 00 e = .test3(6) |
test4
1 2 3 4 5 6 | // 01 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 03 // 00 00 00 00 00 00 00 e = .test4( true ) |
test5
1 2 3 4 5 6 | // 00 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 04 // 00 00 00 00 00 00 00 e = .test5 |
2、枚举只有1个case的情况(其实一个case也多大意义了)
1 2 3 4 5 6 7 8 9 | enum TestEnum { case test1(Int, Int, Int) } var e = TestEnum.test1(10, 20, 30) MemoryLayout.stride(ofValue: e) // 24, 分配占用的空间大小 MemoryLayout.size(ofValue: e) // 24, 实际用到的空间大小 MemoryLayout.alignment(ofValue: e) // 8, 对齐参数 |
test1
1 2 3 4 | // 0A 00 00 00 00 00 00 00 // 14 00 00 00 00 00 00 00 // 1E 00 00 00 00 00 00 00 var e = TestEnum.test1(10, 20, 30) |
这种情况就不需要存储成员值了,直接开辟24个字节存关联值
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!