我们之前提到了在Rust中有一个非常常用的枚举 Option
,它的原型是如下的样子
|
|
它代表了有值和没有值的情况,成员 None
代表没有值,也就是空值的情况,Some(T)
代表了有值的情况,换句话说 Option<T>
代表了一个可能为空的值
Option<T>
枚举是如此有用以至于它甚至被包含在了prelude
之中,你不需要将其显式引入作用域。另外,它的成员也是如此,可以不需要 Option:: 前缀来直接使用 Some 和 None。即便如此 Some(T) 和 None 仍是 Option的成员。
这有什么好处或者说什么用处呢?Rust为什么要这么设计它?它和其他语言中的null
有什么不同?下面我说说我的见解
在其他语言中,空值通常由 null
或 nil
来表示,当一个变量的值是 null
时,如果你尝试使用它,程序很可能会崩溃,因为编译器并不知道这个变量的值是什么,换句话说,编译器并不知道这个变量的值是否是一个有效值,因为null
也是一个值
,只不过它是一个有特殊意义的值 ,它可能在运行时因某种情况被赋予变量,而当你尝试像一个非空值那样使用一个空值,程序很可能就会崩溃。
而Rust通过 Option<T>
将空值的检查放到了编译期,编译器会确保我们在使用值之前处理了为空的情况。
例如这段代码就无法通过编译
|
|
上面的例子会报错, cannot add
Option<i8>
toi8
Rust 不知道该如何将Option<i8>
与i8
相加,因为它们的类型不同。
而要转换为 T
,你就必须处理空值的情况,告诉Rust,如果这个值无效,则返回什么东西
你可能会问,为什么不允许直接用 Option<T>
和其他类型做运算?非要转换一下?
- 第一点是因为类型不同
|
|
- 第二点是因为Rust不允许像一个肯定有效的值那样使用
Option<T>
|
|
简单来说,Rust强制你在使用 Option<T>
之前处理为空的情况
总结一下
Option<T>
是一个代表包含有有效值
和无效值
的类型- 在使用
Option<T>
之前必须将其转换为实际的T
类型 Option<T>
将其他语言中常见的null类型转换异常
的问题,由运行时
转移到了编译期