Enumlar
'enum' anahtar sözcüğü birkaç farklı varyanta sahip bir türün yaratılmasına olanak sağlar:
#[derive(Debug)] enum Direction { Left, Right, } #[derive(Debug)] enum PlayerMove { Pass, // Basit (simple) varyant Run(Direction), // Demet (Tuple) varyantı Teleport { x: u32, y: u32 }, // Yapı (Struct) varyantı } fn main() { let player_move: PlayerMove = PlayerMove::Run(Direction::Left); println!("Sıradaki hamle: {player_move:?}"); }
Önemli Noktalar:
- Numaralandırmalar, bir dizi değeri tek bir tür altında toplamanıza olanak tanır.
Direction
, varyantları olan bir türdür.Direction
'ın iki değeri vardır:Direction::Left
veDirection::Right
.PlayerMove
üç varyantı olan bir türdür. Rust, varyant değerlerine (variant payloads) ek olarak, çalışma zamanında hangi varyantınPlayerMove
değerinde olduğunu bilmesi için bir ayırıcı (discriminant) da depolayacaktır.- Bu, yapıları ve numaralandırmaları karşılaştırmak için iyi bir zaman olabilir:
- Her ikisinde de, alanları olmayan basit bir versiyona (birim yapı) veya farklı alan türlerine sahip bir versiyona (varyant yükleri) sahip olabilirsiniz.
- Bir enum'ın farklı varyantlarını ayrı yapılarla bile uygulayabilirsiniz ancak o zaman da hepsi bir enum'da tanımlanmış olduğunda olacağı gibi aynı türde olmazlardı.
- Rust, ayırıcıyı (discriminant) depolamak için minimum alan kullanır.
-
Gerekirse, gereken en küçük boyuttaki bir tam sayıyı depolar
-
İzin verilen varyant değerleri tüm bit desenlerini kapsamıyorsa, ayırıcıyı kodlamak için geçersiz bit desenleri kullanır ("niş/oyuk/niche optimizasyonu"). Örneğin,
Option<&u8>
,None
varyantı için bir tamsayıya gösterici veyaNULL
depolar. -
Gerekirse ayırıcıyı kontrol edebilirsiniz (örneğin, C ile uyumluluk için):
#[repr(u32)] enum Bar { A, // 0 B = 10000, C, // 10001 } fn main() { println!("A: {}", Bar::A as u32); println!("B: {}", Bar::B as u32); println!("C: {}", Bar::C as u32); }
repr
olmadan, ayırıcı tür 2 baytlık olur, çünkü 10001 2 bayta sığar.
-
Daha Fazlasını Keşfedin
Rust, enum'ların daha az yer kaplamasını sağlamak için kullanabileceği çeşitli optimizasyonlara sahiptir.
-
Null gösterici optimizasyonu: Bazı türler için, Rust
size_of::<T>()
'ninsize_of::<Option<T>>()
'ye eşit olduğunu garanti eder.Bitsel gösterimin pratikte nasıl görünebileceğini göstermek istiyorsanız örnek kod aşağıdadır. Derleyicinin bu gösterimle (representation) ilgili hiçbir garanti sağlamadığını, dolayısıyla bunun tamamen emniyetsiz olduğunu belirtmek önemlidir.
use std::mem::transmute; macro_rules! dbg_bits { ($e:expr, $bit_type:ty) => { println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); }; } fn main() { unsafe { println!("bool:"); dbg_bits!(false, u8); dbg_bits!(true, u8); println!("Option<bool>:"); dbg_bits!(None::<bool>, u8); dbg_bits!(Some(false), u8); dbg_bits!(Some(true), u8); println!("Option<Option<bool>>:"); dbg_bits!(Some(Some(false)), u8); dbg_bits!(Some(Some(true)), u8); dbg_bits!(Some(None::<bool>), u8); dbg_bits!(None::<Option<bool>>, u8); println!("Option<&i32>:"); dbg_bits!(None::<&i32>, usize); dbg_bits!(Some(&0i32), usize); } }