2015-12-31 5 views
1

Есть ли простой способ конвертировать любой IntegerType в Int в Swift. У меня есть словарь, который содержит разные типы целых чисел; UInt8, UInt16 и т. Д. И необходимо преобразовать это в Int. Есть ли более простой способ, кроме переключателя высказывания:Swift - Cast Any IntegerType to Int

let x: UInt8 = 5 
let any: Any = x 

var size: Int 
switch (any) { 
case let value as Int8: size = Int(value) 
case let value as UInt8: size = Int(value) 
case let value as Int16: size = Int(value) 
case let value as UInt16: size = Int(value) 
case let value as Int32: size = Int(value) 
case let value as UInt32: size = Int(value) 
case let value as Int64: size = Int(value) 
case let value as UInt64: size = Int(value) 
case let value as Int: size = Int(value) 
case let value as UInt: size = Int(value) 
default: size = 0 
} 
+0

Вы всегда можете использовать свойство hashValue из любого IntegerType –

+0

Это может работать, но как преобразовать Any в IntegerType? –

+0

if let int = (any as? UInt8) ?. hashValue { print (int) } –

ответ

2

Вашей проблемы заключается в том, что вы позволили Any прийти в картину. В этот момент вы теряете много сил.

Другая проблема, с которой вы сталкиваетесь, заключается в том, что ваш написанный вами код плохо определен, а Свифт сопротивляется вам писать код таким образом (в основном, заставляя вас быть явным). Если вы получили UInt64, нет гарантии, что size будет иметь то же значение, что и value. Это очень распространенная проблема, когда люди ищут автоматический способ преобразования между типами номеров. Swift поощряет вас думать о числовых преобразованиях, потому что они являются общим источником ошибок.

Есть несколько вещей, которые вы можете сделать в зависимости от того, что вы пытаетесь решить. Если вам нужна структура данных, содержащая Int64 или UInt64, это легко. Просто создайте тип, который вы имеете в виду.

enum ParsedNumber { 
    case Signed(Int64) 
    case Unsigned(UInt64) 
} 

let numbers: [String: ParsedNumber] = [:] 

Тогда все ваши значения будут соответствовать этому. Если вам необходимо следить за шириной для последующего, что это не проблема либо:

struct ParsedNumber { 
    enum Value { 
     case Signed(Int64) 
     case Unsigned(UInt64) 
    } 
    let width: Int 
    let value: Value 
} 

let n = ParsedNumber(width: 32, value: .Signed(2)) 

Это чувствует, как проблемы вы решаете. Если с другой стороны, вы знаете свой тип в одной точке (т.е. это Int8, не Any) и просто хотите, чтобы иметь возможность передать его функции, просто сделать функции общие на IntegerType:

func calc<Num: IntegerType>(num: Num) { ... } 

Полезный инструмент по IntegerType - его метод toIntMax(). Это будет ловушка (сбой), если значение слишком велико, поэтому имейте в виду, но это полезный способ преобразования произвольных значений в известный целочисленный тип. Есть также SignedIntegerType и UnsignedIntegerType, если вы уже знаете свой знак. (Вы не можете преобразовать Any в них. Вам нужно уже иметь известный тип где-то.)

+0

Спасибо, я понимаю. Наверное, я могу расширить эту идею до других типов, таких как float, strings. –

+0

Да. Парсер, как и вы, почти наверняка хочет выплюнуть какой-то перемычек, который сдерживает его результаты для типов, которые обрабатываются, и упаковывает их таким образом, который удобен для остальной части вашей программы. Помните, что перечисления могут иметь свои собственные методы, поэтому легко создать 'isString: Bool' или' stringValue: String? 'На перечислении, чтобы его можно было использовать, не требуя операторов switch везде, если вы этого не хотите. –