13 September, 2016

Enums in C# vs. Swift - how to

The concept of a “flagged enum” is quite a powerful one as it allows you to express multiple things with just a simple number (integer). Coming from a .NET background - the ease of flagged enums found in C# is not that easily found in Swift I’ve come to realize. The expression in Swift is somewhat different and honestly a bit difficult to grasp.

Let’s give it a try:


In C# you express an enum like this:

public enum SecurityLevel : Int{
	case NoAccess = 0
	case Employee = 1,
	case LineManager = 2,
	case DivisionManager = 4,
	case RegionalManager = 8,
	case CountryManager = 16}

This constructed example serves a purpose like:

var person = new Person();
person.AccessLevel = 3 //meaning access as Employee AND LineManager

This will allow us to model a Person with multiple access levels (security levels) with just a single integer. An easy way to store in the backend database as well!


So - how does this look in Swift?

public struct securityLevel : OptionsSetType {
	let rawValue : Int
	static let noAccess = securityLevel (rawValue: 0)
	static let employee = securityLevel (rawValue: 1 << 0)
	static let lineManager = securityLevel (rawValue: 1 << 1)
	static let divisionManager = securityLevel (rawValue: 1 << 2)
	static let regionalManager = securityLevel (rawValue: 1 << 3)
	static let countryManager = securityLevel (rawValue: 1 << 4)

Quite a different beast, ey? How can this be the same you are thinking?
The strange << operator is called a bitwise left shift operator and and actually does what it says - it moves all bits in the array to the left by the number specified.

Looking at the securityLevel struct again, we have:

setting the value to noAccess:
0|0|0|0|0|0 = 0
setting the value employee:
0|0|0|0|0|1 = 1
setting the value lineManager:
0|0|0|0|1|0 = 2

combining the values (employee AND lineManager)
0|0|0|0|1|1 = 3

So the left shift stuff is actually initializing the struct with the value of 1, and then it moves all bits a number of slots to the left to end up with a whole new number. In our example with the combined employee and lineManager - we will see first the employee being set (rawValue:1 <<0)

  • init with 1 -> 0|0|0|0|0|1
  • next move it 0 places to the left -> 0|0|0|0|0|1
  • end result = 1

Next is the lineManager value (rawValue: 1 << 1):

  • init with 1 -> 0|0|0|0|0|1
  • next move it 1 places to the left -> 0|0|0|0|1|0
  • end result = 2

When combining the operations (employee AND lineManager) you are actually just performing the above operations in sequence ending up with the value 3.

Easy to understand? Not so much ;-)