Rust 1.95.0 · Edition 2024 · Cargo Workspace
A complete, runnable Cargo workspace teaching Rust to experienced C# / .NET developers. Every concept is shown side-by-side with its C# equivalent, each example is self-contained, and all code compiles on Rust 1.95.0.
- Prerequisites & Setup
- Repository Structure
- How to Run Examples
- C# → Rust Concept Map
- Module Reference
- 1-Week Study Plan
- Glossary
- Capstone Project
- Recommended Resources
# Install rustup (skip if already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Linux/macOS
# or download from https://rustup.rs on Windows
# Install Rust 1.95.0 and set as default
rustup install 1.95.0
rustup default 1.95.0
# Verify
rustc --version # rustc 1.95.0 (...)
cargo --version # cargo 1.95.0 (...)git clone <this-repo>
cd c-sharp-to-rust-learning
# Check all crates compile (fast — no linking)
cargo check --workspace
# Build everything in release mode
cargo build --workspace --release
# Run all tests across the workspace
cargo test --workspace# Install rust-analyzer extension
code --install-extension rust-lang.rust-analyzer
# Optional: better error lenses
code --install-extension usernamehw.errorlensc-sharp-to-rust-learning/
├── Cargo.toml ← Workspace root (shared deps, edition 2024)
├── README.md ← This file
│
├── 01_getting_started/
│ └── src/bin/
│ ├── hello_world.rs ← println!, format!, basic I/O
│ ├── cargo_basics.rs ← Cargo commands cheat-sheet
│ └── rustup_info.rs ← Toolchain management
│
├── 02_syntax_and_basic_types/
│ └── src/bin/
│ ├── variables_mutability.rs ← let, mut, shadowing, inference
│ ├── scalar_types.rs ← int/float/bool/char, overflow
│ ├── compound_types.rs ← tuples, arrays, slices
│ ├── strings.rs ← &str vs String, UTF-8
│ ├── constants_statics.rs ← const, static, const fn
│ └── control_flow.rs ← if/loop/for/match/if let/let-else
│
├── 03_ownership_borrowing_and_moves/
│ └── src/bin/
│ ├── ownership.rs ← Three ownership rules, Drop
│ ├── moves.rs ← Move semantics, partial moves
│ ├── copy_clone.rs ← Copy vs Clone traits
│ └── borrowing.rs ← &T / &mut T, borrow rules, NLL
│
├── 04_references_and_lifetimes/
│ └── src/bin/
│ ├── lifetimes.rs ← 'a annotations, struct lifetimes
│ ├── lifetime_elision.rs ← Three elision rules, use<>
│ └── dangling_refs.rs ← Use-after-free prevention
│
├── 05_structs_enums_and_pattern_matching/
│ └── src/bin/
│ ├── structs.rs ← Named/tuple/unit structs, impl
│ ├── enums.rs ← ADTs, Option<T>, Result<T,E>
│ ├── pattern_matching.rs ← match, guards, bindings, nested
│ └── option_result.rs ← Combinators, ?, From, conversion
│
├── 06_traits_generics_and_impl_blocks/
│ └── src/bin/
│ ├── traits.rs ← Trait definition, default methods
│ ├── generics.rs ← fn/struct generics, where, assoc types
│ ├── trait_objects.rs ← &dyn Trait, Box<dyn>, fat pointer
│ └── advanced_traits.rs ← Operator overloading, Deref, Index
│
├── 07_error_handling/
│ └── src/bin/
│ ├── panic_basics.rs ← panic!, assert!, catch_unwind
│ ├── result_patterns.rs ← ?, chaining, collect, partition
│ ├── thiserror_example.rs ← #[derive(Error)], #[from], chains
│ └── anyhow_example.rs ← anyhow!, bail!, context(), downcast
│
├── 08_collections_and_iterators/
│ └── src/bin/
│ ├── vec_collections.rs ← Vec, VecDeque, BTreeMap, BTreeSet
│ ├── hashmap_hashset.rs ← HashMap CRUD, entry API, HashSet
│ ├── iterators.rs ← All iterator adapters & consumers
│ └── custom_iterators.rs ← impl Iterator, Fibonacci, BST
│
├── 09_closures_and_functional_patterns/
│ └── src/bin/
│ ├── closures.rs ← Fn/FnMut/FnOnce, capture modes
│ ├── function_pointers.rs ← fn type, dispatch tables
│ └── functional_patterns.rs ← map/filter/fold, currying, Cow
│
├── 10_modules_crates_and_workspaces/
│ └── src/bin/
│ ├── modules.rs ← mod, pub, use, crate/super/self
│ ├── visibility.rs ← pub(crate), pub(super), pub(in)
│ └── cargo_features.rs ← #[cfg], features, build.rs
│
├── 11_testing_and_documentation/
│ ├── src/
│ │ ├── lib.rs ← Library with doc tests, proptest
│ │ └── bin/doc_examples.rs ← Doc comment styles
│ └── tests/integration_tests.rs ← Integration tests
│
├── 12_memory_management_and_smart_pointers/
│ └── src/bin/
│ ├── box_pointer.rs ← Box<T>, recursive types
│ ├── rc_arc.rs ← Rc/Arc, Weak, reference cycles
│ ├── cell_refcell.rs ← Cell<T>, RefCell<T>, Rc<RefCell<T>>
│ ├── mutex_rwlock.rs ← Mutex<T>, RwLock, Arc<Mutex>
│ └── deref_drop.rs ← Deref coercion, RAII, Drop order
│
├── 13_concurrency_threads_and_channels/
│ └── src/bin/
│ ├── threads.rs ← thread::spawn, join, scope
│ ├── channels.rs ← mpsc, clone tx, try_recv
│ └── shared_state.rs ← Barrier, Condvar, OnceLock, Atomic
│
├── 14_async_await_and_tokio/
│ └── src/bin/
│ ├── async_basics.rs ← async fn, .await, join!, select!
│ ├── tokio_tasks.rs ← spawn, try_join_all, Semaphore
│ ├── streams.rs ← Stream trait, adapters, channels
│ └── pin_unpin.rs ← Pin<T>, Unpin, stack/heap pinning
│
├── 15_macros/
│ └── src/bin/
│ ├── macro_rules.rs ← macro_rules!, repetition, recursion
│ ├── builtin_macros.rs ← println!, assert!, vec!, env!, cfg!
│ └── derive_macros.rs ← #[derive], #[cfg], attributes
│
├── 16_unsafe_rust/
│ └── src/bin/
│ ├── unsafe_blocks.rs ← 5 unsafe superpowers, safe wrappers
│ └── raw_pointers.rs ← *const/*mut, arithmetic, Box round-trip
│
├── 17_ffi_and_interop/
│ └── src/bin/
│ └── ffi_basics.rs ← extern "C", CString/CStr, #[no_mangle]
│
├── 18_performance_and_benchmarking/
│ ├── src/bin/performance_tips.rs ← Allocation, zero-cost iterators, Cow
│ └── benches/
│ ├── string_bench.rs ← Criterion string benchmarks
│ └── iter_bench.rs ← Criterion iterator benchmarks
│
├── 19_cli_apps/
│ └── src/bin/
│ ├── clap_basics.rs ← clap derive, subcommands, ValueEnum
│ └── file_tool.rs ← wc/grep/head clone, anyhow, stdin
│
├── 20_web_api_project/
│ └── src/bin/
│ └── web_server.rs ← axum CRUD API, State, Json, Path
│
├── 21_advanced_patterns/
│ └── src/bin/
│ ├── builder_pattern.rs ← Fluent builder, validated, phantom-typed
│ ├── newtype_pattern.rs ← Units, validated types, Deref
│ ├── state_machine.rs ← Enum-based state machine
│ └── type_state.rs ← Phantom-typed compile-time states
│
└── 22_csharp_to_rust_migration_guides/
└── src/bin/
├── gc_vs_ownership.rs ← GC pauses vs RAII, Weak<T>
├── classes_vs_structs.rs ← Class → struct+impl, interface → trait
├── linq_vs_iterators.rs ← Every LINQ method mapped to Iterator
├── async_model_comparison.rs ← Task<T> vs Future, cancellation
└── exceptions_vs_results.rs ← throw/catch vs Result<T,E>, ?
Every example is a standalone binary. The bin name is the filename without .rs:
14_async_await_and_tokio/src/bin/streams.rs → cargo run --bin streams
21_advanced_patterns/src/bin/state_machine.rs → cargo run --bin state_machine
All commands below must be run from the workspace root (the folder containing the top-level Cargo.toml).
# List every binary in the workspace:
cargo run --bin 2>&1 | grep " "
# Or just browse the source tree:
find . -path "*/src/bin/*.rs" -printf "%f\n" | sed 's/\.rs$//' | sort
# Windows (PowerShell):
Get-ChildItem -Recurse -Filter "*.rs" -Path "*/src/bin" | Select-Object BaseName | Sort-Object BaseNamecargo run --bin <bin_name>
# Examples:
cargo run --bin hello_world
cargo run --bin ownership
cargo run --bin async_basics
cargo run --bin streams
cargo run --bin state_machine
cargo run --bin performance_tips
cargo run --bin ffi_basicscargo run --release --bin <bin_name>
# Example:
cargo run --release --bin performance_tipscd 14_async_await_and_tokio
cargo run --bin streams
cargo run --bin async_basicscargo run --bin clap_basics -- --help
cargo run --bin clap_basics -- greet --name Alice --times 3
cargo run --bin file_tool -- count src/bin/file_tool.rs
cargo run --bin file_tool -- find . --ext rsThe -- separator tells Cargo to stop parsing its own flags and forward the rest to your program.
# Tests for one binary:
cargo test --bin async_basics
# Tests for one module (package):
cargo test -p async_await_and_tokio
# All tests in the workspace:
cargo test --workspace
# A specific test function by name:
cargo test --bin async_basics -- async_test# All benchmarks:
cargo bench -p performance_and_benchmarking
# One benchmark suite:
cargo bench -p performance_and_benchmarking --bench string_bench
cargo bench -p performance_and_benchmarking --bench iter_benchBenchmarks always run in release mode automatically.
| Module | Bin name | Topic |
|---|---|---|
| 01 | hello_world · cargo_basics · rustup_info |
Getting started |
| 02 | variables_mutability · scalar_types · compound_types · strings · control_flow · constants_statics |
Types & syntax |
| 03 | ownership · moves · copy_clone · borrowing |
Ownership |
| 04 | lifetimes · lifetime_elision · dangling_refs |
Lifetimes |
| 05 | structs · enums · pattern_matching · option_result |
Structs & enums |
| 06 | traits · generics · trait_objects · advanced_traits |
Traits & generics |
| 07 | result_patterns · thiserror_example · anyhow_example · panic_basics |
Error handling |
| 08 | vec_collections · hashmap_hashset · iterators · custom_iterators |
Collections |
| 09 | closures · functional_patterns · function_pointers |
Closures |
| 10 | modules · visibility · cargo_features |
Modules & crates |
| 11 | doc_examples |
Testing & docs |
| 12 | box_pointer · rc_arc · cell_refcell · mutex_rwlock · deref_drop |
Smart pointers |
| 13 | threads · channels · shared_state |
Concurrency |
| 14 | async_basics · tokio_tasks · streams · pin_unpin |
Async / Tokio |
| 15 | macro_rules · derive_macros · builtin_macros |
Macros |
| 16 | unsafe_blocks · raw_pointers |
Unsafe Rust |
| 17 | ffi_basics |
FFI & interop |
| 18 | performance_tips |
Performance |
| 19 | clap_basics · file_tool |
CLI apps |
| 20 | web_server |
Web API (axum) |
| 21 | builder_pattern · newtype_pattern · state_machine · type_state |
Advanced patterns |
| 22 | gc_vs_ownership · classes_vs_structs · linq_vs_iterators · async_model_comparison · exceptions_vs_results |
Migration guides |
| 23 | encapsulation · inheritance_composition · polymorphism · operator_overloading |
OOP in Rust |
| 24 | json_basics · advanced_serde |
Serde serialization |
| 25 | tracing_basics |
Logging & tracing |
| 13+ | send_sync |
Send + Sync (added to module 13) |
| 11+ | unit_testing · proptest_basics |
Testing (added to module 11) |
| C# | Rust |
|---|---|
int, long, uint |
i32, i64, u32, u64 |
double, float |
f64, f32 |
bool |
bool |
char (UTF-16) |
char (Unicode scalar, 4 bytes) |
string (heap, immutable) |
String (owned heap) |
ReadOnlySpan<char> |
&str (borrowed slice) |
T[] |
[T; N] (fixed) / Vec<T> (dynamic) |
List<T> |
Vec<T> |
Dictionary<K,V> |
HashMap<K,V> |
HashSet<T> |
HashSet<T> |
SortedDictionary<K,V> |
BTreeMap<K,V> |
(T1, T2) |
(T1, T2) tuple |
T? nullable |
Option<T> |
IEnumerable<T> |
impl Iterator<Item=T> |
IAsyncEnumerable<T> |
impl Stream<Item=T> |
| C# | Rust |
|---|---|
| GC (non-deterministic) | Ownership (deterministic RAII) |
IDisposable / using |
Drop trait (automatic) |
| Reference type (heap) | Box<T> / Vec<T> / String |
| Value type (stack) | Any T without Box |
| Shared mutable | Arc<Mutex<T>> |
| Shared single-thread | Rc<RefCell<T>> |
WeakReference<T> |
Weak<T> |
GC.KeepAlive(obj) |
Pin<T> |
Span<T> |
&mut [T] |
ReadOnlySpan<T> |
&[T] |
| C# | Rust |
|---|---|
class |
struct + impl |
interface |
trait |
| Abstract method | Trait method (no default) |
| Default interface method | Trait default method |
| Inheritance | Composition + trait impls |
virtual / override |
dyn Trait (vtable dispatch) |
Generic constraint where T : IFoo |
where T: Foo |
static method |
Associated function (no self) |
this |
self |
Property { get; set; } |
Methods fn value(&self) / fn set_value(&mut self) |
sealed class |
All structs are "sealed" by default |
record |
#[derive(Clone, PartialEq, Debug)] struct |
| C# | Rust |
|---|---|
throw new Exception() |
return Err(MyError::...) |
try { } catch { } |
match result { Ok(v) => ..., Err(e) => ... } |
Exception.Message |
e.to_string() (via Display) |
InnerException |
#[source] / #[from] |
InvalidOperationException |
panic!("...") (truly unrecoverable) |
NullReferenceException |
Cannot occur (Option forces check) |
ArgumentException |
Return Err(InvalidInput) from Result |
AggregateException |
Vec<Error> or try_join_all |
| C# | Rust |
|---|---|
Thread |
std::thread::spawn |
Task<T> |
tokio::task::JoinHandle<T> |
Task.WhenAll |
tokio::join! |
Task.WhenAny |
tokio::select! |
Task.Run |
tokio::spawn |
await task |
handle.await.unwrap() |
CancellationToken |
CancellationToken (tokio) / drop future |
Mutex<T> |
std::sync::Mutex<T> |
SemaphoreSlim |
tokio::sync::Semaphore |
ConcurrentQueue<T> |
std::sync::mpsc::channel |
Channel<T> |
tokio::sync::mpsc::channel |
Interlocked |
std::sync::atomic::AtomicXxx |
Volatile.Read/Write |
Ordering::Acquire/Release |
Lazy<T> |
std::sync::OnceLock<T> |
IAsyncEnumerable<T> |
tokio_stream::Stream |
Parallel.ForEachAsync |
JoinSet + spawn per item |
| C# LINQ | Rust Iterator |
|---|---|
.Where(pred) |
.filter(pred) |
.Select(f) |
.map(f) |
.SelectMany(f) |
.flat_map(f) |
.FirstOrDefault() |
.next() or .find() |
.Any(pred) |
.any(pred) |
.All(pred) |
.all(pred) |
.Count() |
.count() |
.Sum() / .Min() / .Max() |
.sum() / .min() / .max() |
.OrderBy(key) |
.sort_by_key() (not lazy) |
.GroupBy(key) |
fold into HashMap |
.Zip(other) |
.zip(other) |
.Concat(other) |
.chain(other) |
.Distinct() |
.collect::<HashSet<_>>() |
.Take(n) / .Skip(n) |
.take(n) / .skip(n) |
.Aggregate(seed, f) |
.fold(seed, f) |
.ToList() |
.collect::<Vec<_>>() |
.ToDictionary(k, v) |
.collect::<HashMap<_, _>>() |
| # | Module | Key Concepts | C# Analogy |
|---|---|---|---|
| 01 | Getting Started | Cargo, rustup, hello world | dotnet new, nuget |
| 02 | Basic Types | Primitives, strings, control flow | C# primitives, switch |
| 03 | Ownership & Moves | Move semantics, Copy, Clone | Value types vs reference types |
| 04 | Lifetimes | Borrow checker, 'a annotations | Ref validity (no direct equiv) |
| 05 | Structs & Enums | ADTs, Option, Result | Classes, nullable types |
| 06 | Traits & Generics | Polymorphism, impl Trait, dyn | Interfaces, generics |
| 07 | Error Handling | Result, ?, thiserror, anyhow | Exception hierarchy |
| 08 | Collections & Iterators | Vec, HashMap, iterator adapters | List, Dictionary, LINQ |
| 09 | Closures | Fn/FnMut/FnOnce, capture | Func<>, Action<>, lambda |
| 10 | Modules & Cargo | pub, use, workspace, features | namespaces, NuGet |
| 11 | Testing | #[test], doc tests, proptest | xUnit, NUnit |
| 12 | Smart Pointers | Box, Rc, Arc, Cell, Mutex | GC, IDisposable |
| 13 | Concurrency | Threads, channels, atomics | Thread, Channel |
| 14 | Async/Tokio | async/await, streams, Pin | Task, IAsyncEnumerable |
| 15 | Macros | macro_rules!, derive, attributes | Source generators |
| 16 | Unsafe | Raw pointers, unsafe blocks | C# unsafe pointer code |
| 17 | FFI | extern "C", P/Invoke from C# | [DllImport] / P/Invoke |
| 18 | Performance | Zero-cost, criterion benchmarks | BenchmarkDotNet |
| 19 | CLI Apps | clap derive, subcommands | System.CommandLine |
| 20 | Web API | axum, REST, State, JSON | ASP.NET Core minimal API |
| 21 | Advanced Patterns | Builder, newtype, type-state | Design patterns |
| 22 | Migration Guides | GC, classes, LINQ, async, errors | Everything above, together |
| 23 | OOP in Rust | Encapsulation, inheritance→composition, polymorphism, operators | Module 06 + 22 |
| 24 | Serde | JSON serialization, attributes, enum tagging | Module 20 |
| 25 | Logging | tracing spans, structured fields, #[instrument] | Module 20 |
| 13+ | Send + Sync | Thread-safety type system, Arc/Mutex guide | Module 13 |
| 11+ | Testing | Unit tests, proptest, cargo test flags | Module 11 |
- Morning: 01 (setup), 02 (types) — focus on
scalar_types.rsandstrings.rs - Afternoon: 03 (ownership) — read all four files; run each example
- Goal: understand why moves happen and when Copy applies
- Morning: 04 (lifetimes) — read
lifetimes.rs, skimdangling_refs.rs - Afternoon: 05 (structs/enums) — focus on
enums.rsandoption_result.rs - Goal: write a
Shapeenum witharea()method; returnResultfrom a function
- Morning: 06 (traits/generics) —
traits.rs,generics.rs,trait_objects.rs - Afternoon: 07 (error handling) — all four files
- Goal: define a trait, implement it for two types, use
?in a chain
- Morning: 08 —
iterators.rs(map/filter/fold) - Afternoon: 09 — closures and functional patterns
- Goal: rewrite a C# LINQ query as a Rust iterator chain
- Morning: 13 — threads, channels, Mutex
- Afternoon: 14 — async/await, tokio::spawn, join!
- Goal: spawn 5 tasks concurrently, collect results
- Morning: 19 — build a CLI app with clap
- Afternoon: 20 — run the axum web server; test with curl
- Goal: add a new endpoint to the web server
- Morning: 21 — builder pattern, type-state
- Afternoon: 22 — read all migration guides; compare with your C# mental model
- Goal: start the capstone project (below)
| Term | Definition |
|---|---|
| Owner | The variable that holds a value and is responsible for freeing it |
| Move | Transfer of ownership from one variable to another; original is invalid |
| Borrow | Temporary access via &T (immutable) or &mut T (mutable) |
| Lifetime | The scope during which a borrow is valid; tracked by the compiler |
| Trait | A set of method signatures (+ defaults); like C# interface |
| impl Trait | Static dispatch — compiler generates one copy per concrete type |
| dyn Trait | Dynamic dispatch — vtable lookup at runtime; like C# virtual |
| Monomorphisation | Each generic instantiation gets its own compiled copy |
| RAII | Resource Acquisition Is Initialisation — resource freed on scope exit |
| Drop | The trait whose drop() is called when a value goes out of scope |
| Option | Some(T) or None — replaces null |
| Result<T,E> | Ok(T) or Err(E) — replaces exceptions |
? operator |
Early-return on Err/None; equivalent to .unwrap() + return |
| Box | Heap-allocated single owner; like new T() in C# value types |
| Rc | Reference-counted single-thread shared ownership |
| Arc | Atomically reference-counted thread-safe shared ownership |
| Cell | Interior mutability for Copy types |
| RefCell | Interior mutability with runtime borrow checks |
| Mutex | Thread-safe interior mutability via OS lock |
| Send | Type is safe to transfer to another thread |
| Sync | Type is safe to share between threads (&T is Send) |
| Future | A lazily-computed async value; C# Task<T> but not started yet |
| executor | The runtime that polls futures (Tokio for async) |
| macro_rules! | Hygienic syntactic macro system (C# has no direct equiv) |
| proc macro | Compile-time code generation via Rust code (C# source generators) |
| workspace | Multiple crates sharing a root Cargo.toml; like a .NET solution |
| crate | A compilation unit; binary crate = exe, library crate = .dll |
| edition | A backwards-compatible language version (2015/2018/2021/2024) |
| unsafe | A block/fn that unlocks 5 specific low-level operations |
| PhantomData | Zero-sized type marker for phantom type parameters |
| newtype | A one-field tuple struct wrapping another type |
| RPIT | Return-Position impl Trait: fn foo() -> impl Iterator<...> |
Build a task manager CLI that demonstrates all major concepts:
tasks add "Buy groceries" --due 2026-06-01 --priority high
tasks list --filter pending --sort due
tasks complete 3
tasks export --format json > tasks.json
- Data model —
Taskstruct with id, title, due date, priority, status (use enum) - Storage — read/write
tasks.jsonviaserde_json - CLI —
clapderive with subcommands (add/list/complete/export) - Error handling —
thiserrorfor domain errors,anyhowin main - Filtering/sorting — iterator chains (map/filter/sort_by)
- Tests — unit tests for domain logic, integration test for CLI output
tasks serve— start an axum web API (module 20 pattern)- Async file I/O via Tokio
- Property-based tests with
proptest - Custom
Displayfor coloured terminal output
| Resource | URL |
|---|---|
| The Rust Book (official) | https://doc.rust-lang.org/book/ |
| Rust by Example | https://doc.rust-lang.org/rust-by-example/ |
| Rustlings exercises | https://github.com/rust-lang/rustlings |
| Comprehensive Rust (Google) | https://google.github.io/comprehensive-rust/ |
| Tokio tutorial | https://tokio.rs/tokio/tutorial |
| Jon Gjengset — Rust for Rustaceans | https://nostarch.com/rust-rustaceans |
| Exercism Rust track | https://exercism.org/tracks/rust |
| This Week in Rust | https://this-week-in-rust.org |
| crates.io | https://crates.io |
| docs.rs (crate documentation) | https://docs.rs |
Generated for Rust 1.95.0 (Edition 2024). All examples compile with cargo check --workspace.