C6 枚举与模式匹配
- 定义枚举
- Option枚举
- 控制流运算符-match
- [if let](#if let)
定义枚举
- 举例:IP地址:IPv4/IPv6
rust
enum IP {
V4,
V6,
}
如何获取枚举值
名称::枚举名
rust
enum IP {
V4,
V6,
}
fn main()
{
let four = IP::V4;
}
枚举变体
- 可以作为struct里面字段的类型 -> 用struct存储枚举类型
rust
enum IPAddrKind {
V4,
V6,
}
struct IpAddr
{
// IPAddrKind作为一个枚举类型,可以作为IpAddr中字段的一个类型
kind: IPAddrKind,
address: String,
}
fn main()
{
let ipA = IpAddr
{
kind: IPAddrKind::V4,
address: String::from("127.0.0.1"),
};
}
将数据附件到枚举的变体中(注意:这和C#中的枚举不太一样)
- 优点:不需要额外使用struct(可以理解为取代了上面的struct套用enum??)
- 每个变体可以用于不同类型以及关联的数据量(关联其他类型的数据)
- 可以在枚举类型中嵌入任意一种类型,也可以是枚举类型
TODO 我暂时还不知道这个有什么作用
rust
enum IpAddr
{
V4(String),
V6(String),
}
rust
enum IpAddr
{
V4(u8,u8,u8,u8),
V6(String),
}
- 一些例子
rust
#[derive(Debug)]
enum IPAddrKind {
V4(u8,u8,u8,u8),
V6(String),
}
fn main()
{
let home = IPAddrKind::V4(127, 0, 0, 1);
let loopback = IPAddrKind::V6(String::from("::1"));
println!("{:#?}", home);
}
标准库中的IpAddr
rust
struct Ipv4Addr{
xxx
}
struct Ipv6Addr{
xxx
}
enum IpAddr{
V4(Ipv4Addr),
V6(Ipv6Addr),
}
一些例子
rust
enum Message{
Quit,
Move { x:i32, y:i32},
Write(String),
ChangeColor(i32,i32,i32),
}
fn main(){
let q = Message::Quit;
let m = Message::Move {x:12, y:16};
let w = Message::Write(String::from("aaa"));
let c = Message::ChangeColor(0,255,255);
}
为枚举定义方法
- 也使用impl关键字
TODO 暂时不知道有什么用
rust
enum Message{
Quit,
Move { x:i32, y:i32},
Write(String),
ChangeColor(i32,i32,i32),
}
impl Message{
// 和struct有点像,第一个参数也是&self
fn call(&self){}
}
fn main(){
let q = Message::Quit;
let m = Message::Move {x:12, y:16};
let w = Message::Write(String::from("aaa"));
let c = Message::ChangeColor(0,255,255);
// 和struct有点像,也是用实例.方法名 进行调用
m.call();
}
Option枚举
Option枚举
- 定义于标准库中
- 在Prelude(预导入模块)中
- 主要用于描述某个值可能存在(某种类型)或者不存在的情况
- 不存在的情况主要是为了取代null
Option的标准库定义
- 定义
rust
enum Option<T>{
Some(T),
None,
}
- 使用方式
- Option
<T> - Some(T)
- None
- Option
注意在使用None时需要提前定义好T的类型,要不然编译器不知道分配什么类型。- let absent_number : Option
<i32>= None;
- let absent_number : Option
- 举例
rust
fn main(){
// T就是i32类型
let some_number = Some(5);
// T是&str, 字符串切片类型
let some_string = Some("A String");
let absent_number : Option<i32> = None;
}
Option<T>比Null好在哪
-
Option
<T>和T是不同类型,不可以直接将Option<T>当成T类型使用 -
例子
rustlet x : i8= 5; let y : Option<i8>= Some(6); // 这里会报错 let z = x + y;- 如果想要x和y能相加,需要将y转化为i8类型
-
如果想使用Option
<T>中的T,需要显示的将它转换为T- 与c#中的null的对比,
rust中需要转换下否则编译都不通过
- 与c#中的null的对比,
C#
string a = null;
// 这里会报错
string b = a + "1234";
控制流运算符-match
match的定义
- 允许一个变量与一系列
模式进行匹配,并执行匹配到的对应模式的代码 - 其中
模式可以是字面值/变量名/通配符 - match需要穷举所有的可能性,对于对于的需要用
_表示 - 格式
rust
match xxx {
a -> hhh,
// 多语句用{}框起来
b -> {
xxxx;
xxx;
},
// 对于不想care的case使用_代替
_ -> (),
}
- 例子
rust
enum Coin{
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny -> 1,
Coin::Nickel -> 5,
Coin::Dime -> 10,
Coin::Quarter -> 25,
}
}
匹配Option<T>
rust
fn main()
{
let five = Some(5);
// Some(6)
let six = plus_one(five);
// None
let none = plus_one(None);
}
fn plus_one(x: Option<i32>) -> Option<i32>
{
match x
{
None -> None,
Some<i> -> Some(i+1),
}
}
if let
- 一种简单的控制流 -> 简单的match
- 格式(感觉类似三元表达式)
rust
if let xxx(表达式) {}
else {}
等效方式:
rust
fn main()
{
let v = Some(0u8);
match v
{
Some(3) -> {
println!("three");
},
_ -> println!("others"),
}
}
rust
fn main()
{
let v = Some(0u8);
if let Some(3) = v {
println!("three");
}
// 可以没有else的分支
else {
println!("others");
}
}
2026/1/7