Skip to content

codefinity/c-sharp-to-rust-learning

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C# to Rust — A Practical Tutorial for .NET Developers

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.


Table of Contents

  1. Prerequisites & Setup
  2. Repository Structure
  3. How to Run Examples
  4. C# → Rust Concept Map
  5. Module Reference
  6. 1-Week Study Plan
  7. Glossary
  8. Capstone Project
  9. Recommended Resources

Prerequisites & Setup

Install Rust 1.95.0

# 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 (...)

Clone and Build

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

VS Code Setup (Recommended)

# Install rust-analyzer extension
code --install-extension rust-lang.rust-analyzer

# Optional: better error lenses
code --install-extension usernamehw.errorlens

Repository Structure

c-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>, ?

How to Run Examples

Naming convention

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).


Discover available bins

# 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 BaseName

Run a single example

cargo 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_basics

Run in release mode (optimised, required for benchmarks)

cargo run --release --bin <bin_name>

# Example:
cargo run --release --bin performance_tips

Run an example from inside its module directory

cd 14_async_await_and_tokio
cargo run --bin streams
cargo run --bin async_basics

Pass arguments to CLI examples (module 19)

cargo 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 rs

The -- separator tells Cargo to stop parsing its own flags and forward the rest to your program.


Run tests

# 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

Run benchmarks (module 18)

# 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_bench

Benchmarks always run in release mode automatically.


Quick-reference: all bins by module

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 Concept Map

Types

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>

Memory

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]

Object-Oriented

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

Error Handling

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

Concurrency

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

Functional / LINQ

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 Reference

# 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

1-Week Study Plan

Day 1 — Foundations (Modules 01–03)

  • Morning: 01 (setup), 02 (types) — focus on scalar_types.rs and strings.rs
  • Afternoon: 03 (ownership) — read all four files; run each example
  • Goal: understand why moves happen and when Copy applies

Day 2 — Borrowing and Types (Modules 04–05)

  • Morning: 04 (lifetimes) — read lifetimes.rs, skim dangling_refs.rs
  • Afternoon: 05 (structs/enums) — focus on enums.rs and option_result.rs
  • Goal: write a Shape enum with area() method; return Result from a function

Day 3 — Traits and Errors (Modules 06–07)

  • 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

Day 4 — Collections and Functional (Modules 08–09)

  • Morning: 08 — iterators.rs (map/filter/fold)
  • Afternoon: 09 — closures and functional patterns
  • Goal: rewrite a C# LINQ query as a Rust iterator chain

Day 5 — Concurrency and Async (Modules 13–14)

  • Morning: 13 — threads, channels, Mutex
  • Afternoon: 14 — async/await, tokio::spawn, join!
  • Goal: spawn 5 tasks concurrently, collect results

Day 6 — Applications (Modules 19–20)

  • 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

Day 7 — Advanced and Review (Modules 21–22)

  • Morning: 21 — builder pattern, type-state
  • Afternoon: 22 — read all migration guides; compare with your C# mental model
  • Goal: start the capstone project (below)

Glossary

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<...>

Capstone Project

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

Requirements

  1. Data modelTask struct with id, title, due date, priority, status (use enum)
  2. Storage — read/write tasks.json via serde_json
  3. CLIclap derive with subcommands (add/list/complete/export)
  4. Error handlingthiserror for domain errors, anyhow in main
  5. Filtering/sorting — iterator chains (map/filter/sort_by)
  6. Tests — unit tests for domain logic, integration test for CLI output

Stretch Goals

  • tasks serve — start an axum web API (module 20 pattern)
  • Async file I/O via Tokio
  • Property-based tests with proptest
  • Custom Display for coloured terminal output

Recommended Resources

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.

About

Rust tutorial for C# / .NET developers. Learn Rust through side-by-side comparisons: ownership vs GC, traits vs interfaces, async/await + Tokio vs Tasks, LINQ vs iterators, FFI, macros, and unsafe. 22 runnable Cargo workspace modules. Rust 1.95

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages