使用 SQLite.Swift 时微妙的投射警告......绑定?去任何 [英] Subtle cast warning when using SQLite.Swift ... Binding? to Any

查看:36
本文介绍了使用 SQLite.Swift 时微妙的投射警告......绑定?去任何的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个,

 导入 SQLitevar r:[[任何]] = []做 {if let stmt = try local.db?.prepare(q) {r = 数组(stmt)}别的 {打印(sql 有问题?")}}抓住{返回[]}

电话

 r = Array(stmt)

给出从绑定?"隐式强制的表达式任何.

事实上,我不知道如何提供默认值以避免此警告,强制解包值以避免此警告,甚至不知道如何使用as Any"显式转换为 Any 以消除此警告.:O

这是一个重现相同警告的独立示例:

struct 绑定 {}struct 语句:IteratorProtocol, Sequence {func next() ->[捆绑?]?{返回零}}让 stmt = 声明()让 r: [[任何]]r = Array(stmt)//警告:从 'Binding?' 隐式强制转换的表达式去任何.

<小时>

相关有趣的问题:

为什么编译器...

...似乎不知道行号,有这样的问题吗?事实上:为什么只有在编译后才会出现警告?

在编译之前,大多数警告都会在您键入时出现在 IDE 中.

这个警告会出现在(a)只有在编译期间才知道,并且(b)编译器不知道行号.

怎么会?有什么区别?

解决方案

您正在使用 Array

这不应该比使用 Array 的序列初始化器更昂贵,因为在任何一种情况下都必须遍历所有内部元素,这是由于差异Swift 如何存储抽象类型值(请参阅此问答了解更多信息).

然而,真的你应该问问自己 r 是否应该是 [[Any]] 类型.我认为没有理由不应该将它键入为 [[Binding?]].这样做既可以消除警告,又可以为您提供更好的类型安全性.

Here's one,

 import SQLite

    var r:[[Any]] = []

    do {
        if let stmt = try local.db?.prepare(q) {
            r = Array(stmt)
        }
        else {
            print("woe in sql?")
        }
    }
    catch { return [] }

the call

 r = Array(stmt)

gives Expression implicitly coerced from 'Binding?' to Any.

And indeed, I do not know how to Provide a default value to avoid this warning, Force-unwrap the value to avoid this warning, or even Explicitly cast to Any with 'as Any' to silence this warning. :O

Here's a self-contained example that reproduces the same warning:

struct Binding {}

struct Statement : IteratorProtocol, Sequence {
    func next() -> [Binding?]? {
        return nil
    }
}

let stmt = Statement()

let r: [[Any]]

r = Array(stmt) // warning: Expression implicitly coerced from 'Binding?' to Any.


Related interesting question:

Why does the compiler ...

... appear to not know the line number, with problems like this? And indeed: why does the warning only arise once you compile?

Most warnings appear right there in the IDE as you're typing, before compilation.

This warning would appear to (a) only be known during compiling and (b) the compiler doesn't know the line number.

How so? What's the difference?

解决方案

You're using Array's sequence initialiser, which has the signature:

init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element

Because you typed r as [[Any]], Element is [Any]. However, the sequence you're passing in has an Iterator.Element type of [Binding?]. Therefore, you're implicitly coercing Binding? to Any, and as per SE-0140, this will invoke a warning – as you're losing the optionality of the inner elements, which is potentially undesirable.

As the proposal says, one way to silence this warning is to add an explicit as Any cast. In your case, this can be achieved by using a nested map(_:):

r = stmt.map { $0.map { $0 as Any } }

This shouldn't be any more costly than using Array's sequence initialiser due to the fact that a walk over all the inner elements will have to be done in either case, due to the difference in how Swift stores abstract-typed values (see this Q&A for more info).

However, really you should be asking yourself whether r should be of type [[Any]]. I see no reason why you shouldn't just type it as [[Binding?]]. Doing so will both get rid of the warning and give you better type-safety.

这篇关于使用 SQLite.Swift 时微妙的投射警告......绑定?去任何的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆