Как вы проверяете идентичность строк в Swift?

Swift, как и некоторые другие языки, имеет оператор идентификации ===, Но кажется, что вы не можете использовать его против строк:

var x = "hello"
var y = "hello"
if x === y {         //ERROR: 'String' does not conform to protocol 'AnyObject'
    println("SAME!")
}else {
    println("DIFFERENT!")
}

Нет ли прямого способа проверить подлинность строк?!... или я что-то упустил?

1 ответ

Решение

Строки в Swift являются типами значений, а не ссылочными типами. То есть они имеют только ценность, а не идентичность. В этом смысле нет смысла проверять, имеют ли две строки одинаковую "идентичность". Если они не являются одной и той же переменной, они разные. Вместо этого вы должны просто проверить, имеют ли они одинаковое значение, используя ==,

Под капотом может быть интернирование. На самом деле, определенно есть:

struct StringBits {
    let underlyingPtr: UnsafeMutablePointer<Void>
    let padding1: UnsafeMutablePointer<Void>
    let padding2: UnsafeMutablePointer<Void>
}

let s1 = "abcd"
let s2 = "abcd"

let bits1 = unsafeBitCast(s1, StringBits.self)
let bits2 = unsafeBitCast(s2, StringBits.self)

println(bits1.underlyingPtr) //      0x0000000117654000
println(bits2.underlyingPtr) // also 0x0000000117654000

Точно так же, если вы инициализируете одну строку из другой, они будут совместно использовать одно и то же хранилище, пока одна из них не будет видоизменена (то есть строки будут копироваться при записи).

Но эти детали скрыты от вас как детали реализации, которые вам не нужно знать. Что касается семантики, s1 а также s2 совершенно не связаны.

Если вас беспокоит производительность, базовый тип String, вероятно, будет использовать указатели на свое хранилище для эффективной проверки на равенство в тех случаях, когда они совместно используют одно и то же хранилище. Массивы (которые реализованы аналогично) делают, как можно увидеть здесь:

struct NeverEqual: Equatable { }

// NOT a correct implementation of ==, since == must be
// reflexive, and this isn’t:
func ==(lhs: NeverEqual, rhs: NeverEqual)->Bool { return false }

let x=[NeverEqual()]
let y=x

// this returns true – because it doesn’t bother comparing the 
// elements, because it knows x and y share the same storage
x==y
Другие вопросы по тегам