为什么Swift语言指南build议使用Int“即使已知值是非负数”?

这是一个关于Swift编程风格的问题,特别是Int vs UInt

Swift编程语言指南build议程序员使用generics有符号整数typesInt即使variables已知是非负数。 从指南 :

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

但是, UInt在32位体系结构上是32位无符号的,在64位体系结构上是64位无符号的,所以在UInt上使用Int没有性能优势。

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

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

在这里,如果代码被写为: 编译时会遇到运行时问题。

 let age:UInt = -3 // this causes a compiler error because -3 is negative 

还有很多其他的情况(例如任何索引集合的东西),在使用UInt会在编译时而不是运行时遇到问题。

所以问题是:Swift编程语言指南中的build议听起来是这样的,使用Int的好处是“即使要存储的值是非负的”也超过了使用UInt的安全优势?

附加说明:已经使用Swift几个星期了,现在明确要求与Cocoa UInt互操作性。 例如, AVFoundation框架在任何需要“计数”的位置使用无符号整数(样本数/帧/通道数等)。 将这些值转换为Int可能会导致严重的错误,其值大于Int.max

我不认为使用UInt是如你所想的那样安全。 正如你所说:

 let age:UInt = -3 

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

 let myAge:Int = 1 let age:UInt = UInt(myAge) - 3 

这也导致了一个编译器错误。 然而,下面(在我看来,在真正的程序中更常见)情况下没有编译器错误,但实际上导致了EXC_BAD_INSTRUCTION运行时错误:

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

以及:

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

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

 if a.aboveZero > 0 { //Do your thing } else { //Handle bad data } 

我甚至可以将它们的build议等同于使用UInt来避免使用隐含的解包选项:除非您确定不会得到任何否定,否则您将得到运行时错误(除了最简单的情况外)。

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

这可以避免将一个Int分配给UInt的问题。 分配给UI的负的Int值会导致较大的值而不是预期的负值。 二者的二进制表示并不区分一种types和另一种types。

而且,两者都是阶级,一个不是另一个的后裔。 构build的类接收Ints不能在没有重载的情况下接收UI,这意味着在两者之间进行转换将是大多数框架接收Ints时使用的UInts的常见任务。 两者之间的转换也可以成为一个非平凡的任务。

前两个段落提到“互操作性”和“在不同号码types之间转换”。 如果不使用UI,则会避免这些问题。