类型转换

C# 和 Rust 在编译时都是静态类型的。因此,一旦声明了一个变量,后续再为它赋值一个不同类型的值是不被允许的 (除非该值可以隐式转换到目标类型)。C# 中有好几种类型转换的方式,Rust中也有和它们相对的存在。

隐式转换

C# 中有隐式转换,Rust 也是(这被称作强制类型转换(Type coercion))。参考这个例子:

int intNumber = 1;
long longNumber = intNumber;

Rust 对于对于强制类型转换更严格:

let int_number: i32 = 1;
let long_number: i64 = int_number; // error: expected `i64`, found `i32`

一个有效的隐式转换的例子,通过使用 子类型(subtyping)

fn bar<'a>() {
    let s: &'static str = "hi";
    let t: &'a str = s;
}

另见:

显式转换

如果转换可能导致丢失信息,C# 需要使用强制转换表达式来显式转换:

double a = 1.2;
int b = (int)a;

当向下转换时,显式转换可能会在运行时失败,并抛出 OverflowExceptionInvalidCastException 之类的异常。

Rust 不提供原始类型之间的强制转换,不过可以使用 asas.rs 关键字来进行显式转换。Rust 中显式转换不会引发 panic。

let int_number: i32 = 1;
let long_number: i64 = int_number as _;

自定义转换

通常,.NET 类型提供用户定义的转换运算符来将一个类型转换成另一个。另外,System.IConvertible 也是为了类型互相转换而存在的。

再 Rust 中,标准库包含将一个值转换成另一种类型的抽象,通过 From trait 和与它对应的 Into。当为一个类型实现 From 时,会自动提供一个默认的 Into 实现(在 Rust 中叫做 通用实现)。下例演示了这两种类型转换:

fn main() {
    let my_id = MyId("id".into()); // 由于为 `String` 实现了 `from<&str>` trait,`into()` 也自动实现了。
    println!("{}", String::from(my_id)); // 这使用 `String` 的 `From<MyId>` 实现。
}

struct MyId(String);

impl From<MyId> for String {
    fn from(MyId(value): MyId) -> Self {
        value
    }
}

另见: