swift影响inout泛型变量的值

时间:2018-03-03 13:14:18

标签: swift generics inout

我想用T变量简化这段代码但是无法成功编译它。希望你能给我路。

这是"重复"代码我想重写:

    func getIntegerValue (listValues: [Any], numValueToRead: Int, readValue: inout Int) -> Bool {
        if numValueToRead < 0 || numValueToRead >= listValues.count {
            return false
        }
        let value = listValues [numValueToRead]
        if type (of: value) == type(of: readValue) {
            readValue = value as! Int
            return true
        } else {
            return false
        }
    }

    func getStringValue (listValues: [Any], numValueToRead: Int, readValue: inout String) -> Bool {
        if numValueToRead < 0 || numValueToRead >= listValues.count {
            return false
        }
        let value = listValues [numValueToRead]
        if type (of: value) == type(of: readValue) {
            readValue = value as! String
            return true
        } else {
            return false
        }
    }

这是我编写的代码但不编译:

func getValue <T> (listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
    if numValueToRead < 0 || numValueToRead >= listValues.count {
        return false
    }
    let value = listValues [numValueToRead]
    if type (of: value) == type(of: readValue) {
        switch value {
        case let integerValue as Int:
            readValue = integerValue
        case let stringValue as String:
            readValue = stringValue
        default:
            return false
        }
        return true
    } else {
        return false
    }
}

对于那些影响,我得到了那些编译错误:  readValue = integerValue - &gt; &#39;诠释&#39;不可转换为&#39; T&#39;  readValue = stringValue - &gt; &#39;字符串&#39;不可转换为&#39; <&#39;

有没有办法用一个使用泛型的独特函数来合成我的两个函数?

4 个答案:

答案 0 :(得分:2)

理论上,您可以通过添加强制转换来进行编译,因为您已经知道value的类型为T

    case let integerValue as Int:
        readValue = integerValue as! T
    case let stringValue as String:
        readValue = stringValue as! T

但更好的解决方案是使用条件转换(as? T)和 条件绑定(if let):

func getValue<T>(listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
    if numValueToRead < 0 || numValueToRead >= listValues.count {
        return false
    }
    let value = listValues[numValueToRead]
    if let tvalue = value as? T {
        readValue = tvalue
        return true
    } else {
        return false
    }
}

然后适用于任意类型,不仅适用于IntString

“更快捷”的方式将返回一个可选值(nil 表示&#34;没有价值&#34;)。然后可以将代码简化为

func getValue<T>(listValues: [Any], numValueToRead: Int) -> T? {
    guard listValues.indices.contains(numValueToRead) else {
        return nil
    }
    return listValues[numValueToRead] as? T
}

答案 1 :(得分:0)

这应该有效:

func getValue <T> (listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
    if numValueToRead < 0 || numValueToRead >= listValues.count {
        return false
    }

    let value = listValues [numValueToRead]
    if type (of: value) == type(of: readValue) {
        if let genericValue = value as? T {
            readValue = genericValue
            return true
        }

        return false
    } else {
        return false
    }
}

答案 2 :(得分:0)

乍一看,该功能被错误命名。当它返回bool时你不能调用函数getValue ...我会称之为变换或修改或者除了获取值之外的东西,因为你没有获得价值。

我认为这种方法更适合您的需求,而不是经过测试应该有效。

min_neg_1

Explenation:返回可选的泛型类型T更安全。你试图施放它,你失败了,你会抛出错误的东西。在我看来,投掷错误的拯救力量更加安全,你知道出了什么问题。

答案 3 :(得分:0)

正如@MartinR指出的那样,返回nil值而不是inout + Bool组合会得到相同的结果,但代码更少,更易读。这是Swift在从Objective-C导入大多数NSError **方法时所采用的路径(即删除了最后一个参数,将它们作为可抛出函数导入)。

如上所述,另一种方法是在Array上添加扩展名以提取值:

extension Array {
    subscript<T>(_ index: Int, as type: T.Type) -> T? {
        guard 0..<count ~= index else { return nil }
        return self[index] as? T
    }
}

let arr: [Any] = [1, "two", 3, "four"]
arr[1, as: String.self] // two
arr[2, as: String.self] // nil