Как сравнить "любые" типы значений

У меня есть несколько типов значений "Any", которые я хочу сравнить.

var any1: Any = 1
var any2: Any = 1

var any3: Any = "test"
var any4: Any = "test"

print(any1 == any2)
print(any2 == any3)
print(any3 == any4)

Использование оператора == показывает ошибку:

"Двоичный оператор" == "не может применяться к двум" Любые "(aka 'protocol < > ')"

Каким образом это можно сделать?

Ответ 1

Единственный способ сделать это - это функция, == от == которая принимает параметр типа, а затем сравнивает значения, если они оба относятся к этому типу:

func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool {
    guard let a = a as? T, let b = b as? T else { return false }

    return a == b
}

Теперь, используя ваши переменные выше, вы можете сравнить их следующим образом:

var any1: Any = 1
var any2: Any = 1

var any3: Any = "test"
var any4: Any = "test"

isEqual(Int.self, a: any1, b: any2)      // true
isEqual(Int.self, a: any2, b: any3)      // false
isEqual(String.self, a: any3, b: any4)   // true

Ответ 2

Чтобы использовать оператор ==, тип должен соответствовать протоколу Equatable. Протокол Any не соответствует протоколу Equatable, поэтому нет возможности сравнить два значения Any. Это логично - Any является слишком широким термином - значения не могут иметь "общего знаменателя".

Что еще, Swift не позволяет сравнивать два значения Equatable, которые имеют другой тип. Например. оба Int и String соответствуют Equatable, но 1 == "1" не компилируется. Причиной этого является объявление протокола == in Equatable: func ==(lhs: Self, rhs: Self) -> Bool. Это "Я" в основном означает, что оба аргумента должны иметь один и тот же тип. Это он вроде заполнителя - в реализации для определенного типа, Self следует заменить на имя этого типа.

Ответ 3

Мы можем решить это следующим образом

enum SwiftDataType
{
    case String
    case Int
    case Int64
    case Double
    case Bool
    case Undefined
}

func getType( of : Any ) -> SwiftDataType
{
    if let type = of as? String
    {
        return SwiftDataType.String
    }
    else if let type = of as? Int
    {
        return SwiftDataType.Int
    }
    else if let type = of as? Int64
    {
        return SwiftDataType.Int64
    }
    else if let type = of as? Double
    {
        return SwiftDataType.Double
    }
    else if let type = of as? Bool
    {
        return SwiftDataType.Bool
    }
    else
    {
        return SwiftDataType.Undefined
    }
}

func isEqual( a : Any, b : Any ) -> Bool
{
    let aType : SwiftDataType = getType( of : a )
    let bType : SwiftDataType = getType( of : b )
    if aType != bType
    {
        print("Type is not Equal -> \(aType)")
        return false
    }
    else
    {
        switch aType  {
        case SwiftDataType.String :
            guard let aValue = type as? String, let bValue = rtype as? String else
            {
                return false
            }
            return aValue == bValue

        case SwiftDataType.Int :
            guard let aValue = type as? Int, let bValue = rtype as? Int else
            {
                return false
            }
            return aValue == bValue

        case SwiftDataType.Int64 :
            guard let aValue = type as? Int64, let bValue = rtype as? Int64 else
            {
                return false
            }
            return aValue == bValue

        case SwiftDataType.Double :
            guard let aValue = type as? Double, let bValue = rtype as? Double else
            {
                return false
            }
            return aValue == bValue

        case SwiftDataType.Bool :
            guard let aValue = type as?  Bool, let bValue = rtype as? Bool else
            {
                return false
            }
            return aValue == bValue

        default:
            return false
        }
    }
}