【问题标题】:Swift Cast as Generic crashing with UIntSwift Cast as Generic 与 UInt 一起崩溃
【发布时间】:2014-09-18 06:47:07
【问题描述】:

如果与它一起使用的数组是 UInt 类型,为什么下面的 Array 扩展会崩溃,但如果数组是 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);

产生的错误:

Playground 执行失败:错误:执行被中断,原因:EXC_BREAKPOINT(代码=EXC_I386_BPT,子代码=0x0)。 进程一直停留在被中断的地方,使用“thread return -x”返回到表达式求值前的状态。 * 线程#1:tid = 0x27a3c, 0x00000001079d3f27 libswift_stdlib_core.dylibswift_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

【问题讨论】:

标签: arrays generics swift uint


【解决方案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,因为它已经在数组本身中定义了。

【讨论】:

  • 感谢您的快速解释和示例!似乎扩展不适合这个。
  • 也许我还没有看到灵活性,但我相信简单的 indexOf 调用不需要闭包。
  • @Avalon,在这种情况下,闭包只是“必要的”,因为您不能保证存储在数组中的所有类型都是相等的。它为您提供了额外的灵活性,可以通过一种方法进行无限类型的测试以查找对象。例如,您可以使用{$0 &gt; 234} 查找大于 234 的第一个索引。您还可以使用 {$0 === someObj} 查找存储引用类型(类类型)的数组
  • 我明白了!是的,这很灵活。谢谢(你的)信息。我会考虑这两种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-27
  • 2017-06-30
相关资源
最近更新 更多