型別轉換 as
本集目標
學會用 as 做數字型別轉換,以及更安全的替代方案。
概念說明
基本用法
第 1 章學過 Rust 不會自動轉型。需要轉換時用 as:
fn main() {
let x: i32 = 42;
let y: f64 = x as f64;
let a: f64 = 3.99;
let b: i32 = a as i32; // 3,截斷小數,不是四捨五入
}
整數之間
小轉大——值不會變:
fn main() {
let x: u8 = 200;
let y: u32 = x as u32; // 200
}
大轉小——靜默截斷,不會報錯:
fn main() {
let x: u32 = 300;
let y: u8 = x as u8; // 44!300 = 256 + 44,只留最低的 8 個位元
}
有號無號之間也可能出意外:
fn main() {
let x: i32 = -1;
let y: u32 = x as u32; // 4294967295
}
From / Into:更安全的選擇
第 5 章學過 From 和 Into。它們只在轉換保證不會失敗的時候才存在:
fn main() {
let x: i32 = 42;
let y: f64 = f64::from(x); // OK
let z: i32 = i32::from(3.14_f64); // 編譯錯誤!不保證安全
}
TryFrom / TryInto
可能失敗的轉換用 TryFrom——回傳 Result:
use std::convert::TryFrom;
fn main() {
let x: u32 = 300;
let result = u8::try_from(x); // Err
let y: u32 = 42;
let result = u8::try_from(y); // Ok(42)
}
什麼時候用哪個
- 能用
From/Into就用——編譯期保證安全 - 可能失敗用
TryFrom/TryInto——回傳Result as只在你確實知道自己在做什麼的時候用
範例程式碼
use std::convert::TryFrom;
fn main() {
// as 基本轉換
let x: i32 = 42;
let y: f64 = x as f64;
println!("i32 {} → f64 {}", x, y);
let a: f64 = 3.99;
let b: i32 = a as i32;
println!("f64 {} → i32 {}(截斷,不是四捨五入)", a, b);
// 危險的靜默截斷
let big: u32 = 300;
let small: u8 = big as u8;
println!("u32 {} → u8 {}(靜默截斷!)", big, small);
// From:安全
let safe: f64 = f64::from(42_i32);
println!("From:{}", safe);
// TryFrom:可能失敗
match u8::try_from(300_u32) {
Ok(v) => println!("TryFrom 成功:{}", v),
Err(e) => println!("TryFrom 失敗:{}", e),
}
match u8::try_from(42_u32) {
Ok(v) => println!("TryFrom 成功:{}", v),
Err(e) => println!("TryFrom 失敗:{}", e),
}
}
重點整理
as做數字型別轉換:浮點轉整數截斷小數,大整數轉小整數靜默截斷From/Into:只存在於保證安全的轉換TryFrom/TryInto:可能失敗的轉換,回傳Result- 優先用
From,其次TryFrom,最後才as