1

次の配列拡張で使用される配列が UInt 型の場合にクラッシュするのに、配列が Int または String 型の場合に機能するのはなぜですか?

extension Array
{
func indexOf<T:Equatable>(value:T) -> Int?
{
    for (i, val) in enumerate(self)
    {
        if (val as T == value)
        {
            return i;
        }
    }
    return nil;
}
}

var a:[UInt] = [243, 234, 1, 212, 3, 56, 88, 11, 77];
var i = a.indexOf(234);

生成されたエラー:

プレイグラウンドの実行に失敗しました: エラー: 実行が中断されました。理由: EXC_BREAKPOINT (コード=EXC_I386_BPT、サブコード=0x0)。プロセスは中断された時点で残っています。"thread return -x" を使用して、式の評価前の状態に戻します。* スレッド #1: tid = 0x27a3c, 0x00000001079d3f27 libswift_stdlib_core.dylib swift_dynamicCast + 1063, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0) * frame #0: 0x00000001079d3f27 libswift_stdlib_core.dylibswift_dynamicCast + 1063 フレーム #1: 0x00000001137bbbc8

4

1 に答える 1

1

問題は、定義した が配列に格納されているT: Equatableと無関係であることです。Tを行うval as Tと、配列値の型から、T同等である必要がある新しいローカルに変換されます。

リテラルで呼び出す場合、型が拡張によって一致するように強制されないため、indexOf格納されているのと同じ型に強制されません。a

配列内のオブジェクトのインデックスを取得する関数を使用することをお勧めします。

func indexOfObject<T : Equatable>(object: T, inArray collection: [T]) -> Int? {
    var index : Int = 0
    for testObject in collection {
        if testObject == object {
            return index
        }
        index++
    }
    return nil
}

Tこれにより、型が等価であり、渡されたオブジェクトの型一致することが厳密に強制されます。

さらに良いことに、次のような拡張機能を使用することもできます。

extension Array {
    func indexOfObjectPassingTest(test: (object: T) -> Bool) -> Int? {
        var index : Int = 0
        for object in self {
            if test(object: object) {
                return index
            }
            index++
        }
        return nil
    }
}

これはより柔軟で、次のことができます。

var i = a.indexOfObjectPassingTest({$0 == 234})

Tメソッドは配列自体で既に定義されているため、定義していないことにも注意してください。

于 2014-07-26T15:14:11.827 に答える