swift影响inout通用变量的值

swift影响inout通用变量的值,swift,generics,inout,Swift,Generics,Inout,我想用一个T变量简化这段代码,但未能成功编译它。希望你能给我指路 下面是我想重写的“重复”代码: func getIntegerValue (listValues: [Any], numValueToRead: Int, readValue: inout Int) -> Bool { if numValueToRead < 0 || numValueToRead >= listValues.count { return false

我想用一个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 getIntegerValue(listValues:[Any],numValueToRead:Int,readValue:inout Int)->Bool{
如果numValueToRead<0 | | numValueToRead>=listValues.count{
返回错误
}
let value=listValues[numValueToRead]
如果类型(of:value)=类型(of:readValue){
readValue=值为!Int
返回真值
}否则{
返回错误
}
}
func getStringValue(listValues:[Any],numValueToRead:Int,readValue:inout String)->Bool{
如果numValueToRead<0 | | numValueToRead>=listValues.count{
返回错误
}
let value=listValues[numValueToRead]
如果类型(of:value)=类型(of:readValue){
readValue=值为!字符串
返回真值
}否则{
返回错误
}
}
以下是我编写但未编译的代码:

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
    }
}
func-getValue(listValues:[Any],numValueToRead:Int,readValue:inout T)->Bool{
如果numValueToRead<0 | | numValueToRead>=listValues.count{
返回错误
}
let value=listValues[numValueToRead]
如果类型(of:value)=类型(of:readValue){
开关量{
case let integerValue为Int:
readValue=整数值
case let stringValue作为字符串:
readValue=stringValue
违约:
返回错误
}
返回真值
}否则{
返回错误
}
}
对于这些矫揉造作,我得到了这些编译错误: readValue=integerValue->“Int”不能转换为“T” readValue=stringValue->“String”不能转换为“T”


有没有一种方法可以使用泛型将我的两个函数合成为一个唯一的函数?

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

    case let integerValue as Int:
        readValue = integerValue as! T
    case let stringValue as String:
        readValue = stringValue as! T
但更好的解决方案是使用条件强制转换(
as?T
)和 条件绑定(
如果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 type (of: value) == type(of: readValue) {
        if let genericValue = value as? T {
            readValue = genericValue
            return true
        }

        return false
    } else {
        return false
    }
}
func-getValue(listValues:[Any],numValueToRead:Int,readValue:inout T)->Bool{
如果numValueToRead<0 | | numValueToRead>=listValues.count{
返回错误
}
let value=listValues[numValueToRead]
如果类型(of:value)=类型(of:readValue){
如果让genericValue=值为?T{
readValue=genericValue
返回真值
}
返回错误
}否则{
返回错误
}
}

乍一看,函数的名称是错误的。当函数getValue返回布尔值时,不能调用它。。。我会称之为转换或修改,或者其他一些东西,而不是获取值,因为您并没有获取值

我认为这种方法更适合你的需要,而不是测试它应该工作

func transformValue<T>(from listValues: [Any], numValueToRead: Int, readValue: inout T?) throws -> Bool {

    // Guard suits better this case...
    guard numValueToRead > 0 || numValueToRead < listValues.count else { return false }

    let value = listValues[numValueToRead]
    if type (of: value) == type(of: readValue) {
        guard let value =  value as? T else {
            throw NSError(
                domain: "Smth",
                code: 1,
                userInfo: ["Description": "Failed to cast to generic type T"]
            )
        }
        readValue = value as? T
        return true
    }
    return false // No need to call else...
}
func transformValue(来自listValues:[Any],numValueToRead:Int,readValue:inout T?)抛出->Bool{
//警卫更适合这个案子。。。
guard numValueToRead>0 | | numValueToRead

解释:返回可选的泛型类型T更安全。你试图抛出它,你失败了,你抛出了错误的东西出了问题。在我看来,用投掷错误来保存力量投射是更安全的方法,你知道哪里出了问题,所以

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

话虽如此,另一种方法是在
数组
上添加扩展以提取值:

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
扩展数组{
下标(uu-index:Int,as-type:T.type)->T{
守卫0。。
func transformValue<T>(from listValues: [Any], numValueToRead: Int, readValue: inout T?) throws -> Bool {

    // Guard suits better this case...
    guard numValueToRead > 0 || numValueToRead < listValues.count else { return false }

    let value = listValues[numValueToRead]
    if type (of: value) == type(of: readValue) {
        guard let value =  value as? T else {
            throw NSError(
                domain: "Smth",
                code: 1,
                userInfo: ["Description": "Failed to cast to generic type T"]
            )
        }
        readValue = value as? T
        return true
    }
    return false // No need to call else...
}
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