为什么Swift语言指南建议使用Int"即使知道值是非负的"?

j b*_*j b 50 types coding-style type-safety swift

这是一个关于雨燕的编程风格的问题,特别是IntVS UInt.

Swift编程语言指南建议程序员使用通用的有符号整数类型,Int即使已知变量是非负的.从指南:

仅当您特别需要与平台的本机字大小相同的无符号整数类型时才使用UInt.如果不是这种情况,则优选Int,即使已知要存储的值是非负的.Int对整数值的一致使用有助于代码互操作性,避免在不同数字类型之间进行转换,并匹配整数类型推断,如类型安全和类型推断中所述.

但是,UInt在32位体系结构上将是32位无符号,在64位体系结构上将是64位无符号,因此使用Intover 没有性能优势UInt.

相比之下,Swift指南给出了一个后面的例子:

让age = -3
断言(年龄> = 0,"一个人的年龄不能小于零")
//这会导致断言触发,因为年龄不是> = 0

这里,如果代码编写为:编译时,可以在编译时捕获运行时问题:

let age:UInt = -3  
// this causes a compiler error because -3 is negative
Run Code Online (Sandbox Code Playgroud)

还有许多其他情况(例如,将索引集合的任何东西)使用a UInt会在编译时而不是运行时捕获问题.

所以问题:是雨燕编程语言引导声音的意见,并就使用的好处Int"即使要存储的已知非负的值"大于使用的安全优势UInt

附加说明:使用Swift几周之后,现在很清楚,需要与Cocoa 进行互操作UInt.例如,AVFoundation框架在需要"计数"的任何地方使用无符号整数(样本数/样本数/通道数等).将这些值转换为Int可能会导致严重错误,其中值大于Int.max

Nic*_*ley 20

我认为使用UInt并不像你想象的那样安全.如你所说:

let age:UInt = -3
Run Code Online (Sandbox Code Playgroud)

导致编译器错误.我也尝试过:

let myAge:Int = 1
let age:UInt = UInt(myAge) - 3
Run Code Online (Sandbox Code Playgroud)

这也导致编译器错误.但是以下(在我看来在实际程序中更常见)场景没有编译器错误,但实际上导致运行时错误EXC_BAD_INSTRUCTION:

func sub10(num: Int) -> UInt {
    return UInt(num - 10) //Runtime error when num < 10
}
sub10(4)
Run Code Online (Sandbox Code Playgroud)

以及:

class A {
    var aboveZero:UInt
    init() { aboveZero = 1 }
}
let a = A()
a.aboveZero = a.aboveZero - 10 //Runtime error
Run Code Online (Sandbox Code Playgroud)

如果这些是普通Int的,而不是崩溃,你可以添加代码来检查你的条件:

if a.aboveZero > 0 {
    //Do your thing
} else {
    //Handle bad data
}
Run Code Online (Sandbox Code Playgroud)

我甚至可以将他们的建议等同于使用UInts反对使用隐式解包的选项的建议:除非你确定你不会得到任何否定,否则不要这样做,因为否则你会得到运行时错误(除了在最简单的情况下).

  • 您可以轻松地为"UInt"案例添加这些检查; 你只需要确认`num`和`a.aboveZero`是`> = 10`. (3认同)
  • 另外,您可以使用 num &amp;- 10 禁用运行时溢出检查。 (2认同)

BTR*_*RUE 1

它在你的问题中说......“对整数值一致使用 Int 有助于代码互操作性,避免在不同数字类型之间进行转换的需要,并匹配整数类型推断,如类型安全和类型推断中所述。”

这避免了将 Int 分配给 UInt 等问题。分配给 UInt 的负 Int 值会导致较大的值,而不是预期的负值。两者的二进制表示形式并不区分一种类型和另一种类型。

而且,两者都是阶级,一个不是另一个的后代。构建的接收 Int 的类在没有重载的情况下无法接收 UInt,这意味着当大多数框架接收 Int 时,两者之间的转换将是使用 UInt 的常见任务。两者之间的转换也可能成为一项不简单的任务。

前两段谈到“互操作性”和“不同数字类型之间的转换”。如果不使用 UInt 就可以避免出现问题。

  • 是的,这实际上是关于*与 Swift 框架的互操作性*。我仍然认为一般来说,对已知的非负值使用无符号整数更安全,但我同意对于每种类型的所有可能值,两种类型之间没有合理的转换。因此,如果互操作性比安全性更受青睐,那么我理解尽可能使用 Int 的设计选择。 (2认同)