使用 SQLite.Swift 时的细微投射警告 ... 绑定?去任何
Subtle cast warning when using SQLite.Swift ... Binding? to Any
这是一个,
import SQLite
var r:[[Any]] = []
do {
if let stmt = try local.db?.prepare(q) {
r = Array(stmt)
}
else {
print("woe in sql?")
}
}
catch { return [] }
来电
r = Array(stmt)
给出从 'Binding?' 隐式强制转换为 Any 的 表达式。
事实上,我不知道如何提供一个默认值来避免这个警告,Force-unwrap这个值来避免这个警告,或者甚至用 'as Any' 显式地转换成 Any 来消除这个警告。 :O
这是一个重现相同警告的 self-contained 示例:
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.
相关有趣问题:
为什么编译器...
...好像不知道行号,有这样的问题?确实:为什么警告只在编译后出现?
编译前,大多数警告会在您输入时出现在 IDE 中。
这个警告似乎 (a) 只有在编译期间才知道,而 (b) 编译器不知道该行数.
怎么会这样?有什么区别?
您正在使用 Array
的 sequence initialiser,其签名为:
init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element
因为您输入 r
为 [[Any]]
,Element
为 [Any]
。但是,您传入的序列有一个 Iterator.Element
type of [Binding?]
. Therefore, you're implicitly coercing Binding?
to Any
, and as per SE-0140,这将引发警告 – 因为您正在失去内部元素的可选性,这可能是不受欢迎的。
如提案所述,消除此警告的一种方法是添加显式 as Any
转换。在您的情况下,这可以通过使用嵌套的 map(_:)
:
来实现
r = stmt.map { [=11=].map { [=11=] as Any } }
这应该不会比使用 Array
的序列初始化器更昂贵,因为在任何一种情况下都必须遍历所有内部元素,这是由于Swift 如何存储 abstract-typed 值(有关详细信息,请参阅 )。
然而,真的你应该问问自己 r
是否应该是 [[Any]]
类型。我看不出为什么你不应该将其键入 [[Binding?]]
。这样做既可以消除警告,又可以给你更好的 type-safety.
这是一个,
import SQLite
var r:[[Any]] = []
do {
if let stmt = try local.db?.prepare(q) {
r = Array(stmt)
}
else {
print("woe in sql?")
}
}
catch { return [] }
来电
r = Array(stmt)
给出从 'Binding?' 隐式强制转换为 Any 的 表达式。
事实上,我不知道如何提供一个默认值来避免这个警告,Force-unwrap这个值来避免这个警告,或者甚至用 'as Any' 显式地转换成 Any 来消除这个警告。 :O
这是一个重现相同警告的 self-contained 示例:
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.
相关有趣问题:
为什么编译器...
...好像不知道行号,有这样的问题?确实:为什么警告只在编译后出现?
编译前,大多数警告会在您输入时出现在 IDE 中。
这个警告似乎 (a) 只有在编译期间才知道,而 (b) 编译器不知道该行数.
怎么会这样?有什么区别?
您正在使用 Array
的 sequence initialiser,其签名为:
init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element
因为您输入 r
为 [[Any]]
,Element
为 [Any]
。但是,您传入的序列有一个 Iterator.Element
type of [Binding?]
. Therefore, you're implicitly coercing Binding?
to Any
, and as per SE-0140,这将引发警告 – 因为您正在失去内部元素的可选性,这可能是不受欢迎的。
如提案所述,消除此警告的一种方法是添加显式 as Any
转换。在您的情况下,这可以通过使用嵌套的 map(_:)
:
r = stmt.map { [=11=].map { [=11=] as Any } }
这应该不会比使用 Array
的序列初始化器更昂贵,因为在任何一种情况下都必须遍历所有内部元素,这是由于Swift 如何存储 abstract-typed 值(有关详细信息,请参阅
然而,真的你应该问问自己 r
是否应该是 [[Any]]
类型。我看不出为什么你不应该将其键入 [[Binding?]]
。这样做既可以消除警告,又可以给你更好的 type-safety.