### Rust Cargo.toml File Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print An example `Cargo.toml` file for a Rust package, specifying the package name, version, and its dependencies. This file is central to Cargo's build system, defining project metadata and external crates. ```toml [package] name = "hello_world" version = "0.1.0" [dependencies] tokio = "1.0.0" ``` -------------------------------- ### Rust Cargo Project Structure Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Demonstrates the conventional layout for a Rust Cargo package, including directories for source code (`src/`), benchmarks (`benches/`), examples (`examples/`), and integration tests (`tests/`). Key configuration files like `Cargo.toml` and `Cargo.lock` reside at the package root. ```text .\n+-- Cargo.lock +-- Cargo.toml +-- src/ |   +-- lib.rs |   +-- main.rs +-- benches/ |   +-- some-bench.rs +-- examples/ |   +-- some-example.rs +-- tests/ +-- some-integration-test.rs ``` -------------------------------- ### Structured Logging in Rust with Tracing Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/logging-and-tracing/index Illustrates structured logging in Rust using the 'tracing' framework and 'tracing_subscriber'. This example sets up a console subscriber and logs an informational message with a named field, similar to the C# example. ```rust fn main() { // install global default ("console") collector. tracing_subscriber::fmt().init(); tracing::info!("Hello {Day}.", Day = "Thursday"); // Hello Thursday. } ``` -------------------------------- ### .NET Project File Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print A sample `.csproj` file for a .NET project, defining project output type, target framework, and package dependencies. This file dictates build options and lists external libraries required by the project. ```xml Exe net6.0 ``` -------------------------------- ### .NET Project Structure Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Illustrates the typical directory structure for a .NET solution containing a class library and an xUnit test project, as generated by Visual Studio 2022. Each project has its own directory and `.csproj` file, with a solution file (`.sln`) at the root. ```text .\n| SampleClassLibrary.sln +---SampleClassLibrary | Class1.cs | SampleClassLibrary.csproj +---SampleTestProject SampleTestProject.csproj UnitTest1.cs Usings.cs ``` -------------------------------- ### Creating and Modifying Dictionaries/HashMaps in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Shows how to create and populate key-value collections, comparing C#'s Dictionary with Rust's HashMap. Both examples initialize a map with entries and then add a new entry. ```csharp var something = new Dictionary { { "Foo", "Bar" }, { "Baz", "Qux" } }; something.Add("hi", "there"); ``` ```rust let mut something = HashMap::from([ ("Foo".to_owned(), "Bar".to_owned()), ("Baz".to_owned(), "Qux".to_owned()) ]); something.insert("hi".to_owned(), "there".to_owned()); ``` -------------------------------- ### Using Tuples in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Illustrates the usage of tuples for grouping multiple values. The C# example shows accessing tuple elements by Item1 and Item2, while the Rust example demonstrates accessing by index (0, 1) and also tuple deconstruction. ```csharp var something = (1, 2) Console.WriteLine($"a = {something.Item1} b = {something.Item2}"); ``` ```rust let something = (1, 2); println!("a = {} b = {}", something.0, something.1); // deconstruction supported let (a, b) = something; println!("a = {} b = {}", a, b); ``` -------------------------------- ### .NET Assertion Example (xUnit) Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/testing/index An example of an assertion using the xUnit.net framework in C#/.NET. It checks if the length of a string is equal to a specified value, demonstrating a common testing pattern in the .NET ecosystem. ```csharp [Fact] public void Something_Is_The_Right_Length() { var value = "something"; Assert.Equal(9, value.Length); } ``` -------------------------------- ### C#: LINQ Query Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/linq/index This C# code demonstrates a LINQ query that generates a range of numbers, filters for even numbers, flattens the result by creating another range for each even number, and then aggregates the sum of all numbers generated. ```csharp var result = Enumerable.Range(0, 10) .Where(x => x % 2 == 0) .SelectMany(x => Enumerable.Range(0, x)) .Aggregate(0, (acc, x) => acc + x); Console.WriteLine(result); // 50 ``` -------------------------------- ### Handle File I/O Exception in C# Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/exception-handling Provides an example of handling potential 'IOException' during file writing in C# using a 'try-catch' block. This demonstrates how to gracefully manage errors in .NET. ```csharp void Write() { try { File.WriteAllText("file.txt", "content"); } catch (IOException) { Console.WriteLine("Writing to file failed."); } } ``` -------------------------------- ### Overload '+' Operator for Fraction Type in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Demonstrates how to overload the '+' operator for a custom 'Fraction' type in both C# and Rust. This allows for intuitive arithmetic operations on fraction objects. The C# example uses a record struct, while the Rust example utilizes traits for operator overloading. ```csharp Console.WriteLine(new Fraction(5, 4) + new Fraction(1, 2)); // 14/8 public readonly record struct Fraction(int Numerator, int Denominator) { public static Fraction operator +(Fraction a, Fraction b) => new(a.Numerator * b.Denominator + b.Numerator * a.Denominator, a.Denominator * b.Denominator); public override string ToString() => $"{Numerator}/{Denominator}"; } ``` ```rust use std::{fmt::{Display, Formatter, Result}, ops::Add}; struct Fraction { numerator: i32, denominator: i32, } impl Display for Fraction { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.write_fmt(format_args!("{}/வைக்", self.numerator, self.denominator)) } } impl Add for Fraction { type Output = Fraction; fn add(self, rhs: Fraction) -> Fraction { Fraction { numerator: self.numerator * rhs.denominator + rhs.numerator * self.denominator, denominator: self.denominator * rhs.denominator, } } } fn main() { println!( "{}", Fraction { numerator: 5, denominator: 4 } + Fraction { numerator: 1, denominator: 2 } ); // 14/8 } ``` -------------------------------- ### Launch and Join Thread: C# vs Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/threading/index Demonstrates how to create a new thread, execute a task, and then wait for its completion in both C#/.NET and Rust. In Rust, thread creation and starting are combined into a single `thread::spawn` call. ```csharp using System; using System.Threading; var thread = new Thread(() => Console.WriteLine("Hello from a thread!")); thread.Start(); thread.Join(); // wait for thread to finish ``` ```rust use std::thread; fn main() { let thread = thread::spawn(|| println!("Hello from a thread!")); thread.join().unwrap(); // wait for thread to finish } ``` -------------------------------- ### Structured Logging in C# with ILogger Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/logging-and-tracing/index Demonstrates structured logging using Microsoft's ILogger interface in C#. This example utilizes LoggerFactory to create a console logger and logs an informational message with a structured parameter. ```csharp using Microsoft.Extensions.Logging; using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); var logger = loggerFactory.CreateLogger(); logger.LogInformation("Hello {Day}.", "Thursday"); // Hello Thursday. ``` -------------------------------- ### C# Equality Comparison Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/equality Demonstrates value and reference equality checks in C# using a `record` type. It shows how the `==` operator and `Equals` method perform value equality, while `ReferenceEquals` checks for reference equality. ```csharp var a = new Point(1, 2); var b = new Point(1, 2); var c = a; Console.WriteLine(a == b); // (1) True Console.WriteLine(a.Equals(b)); // (1) True Console.WriteLine(a.Equals(new Point(2, 2))); // (1) False Console.WriteLine(ReferenceEquals(a, b)); // (2) False Console.WriteLine(ReferenceEquals(a, c)); // (2) True record Point(int X, int Y); ``` -------------------------------- ### Rust Assertion Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/testing/index Demonstrates the use of the built-in `assert_eq!` macro in Rust for testing equality, similar to `Assert.Equal` in .NET's xUnit. This macro is part of Rust's standard library and requires no external crates for basic assertions. ```rust #[test] fn something_is_the_right_length() { let value = "something"; assert_eq!(9, value.len()); } ``` -------------------------------- ### Rust Enum Try From Integer Usage Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/custom-types/enums Demonstrates the usage of the `try_from_i32` function for a Rust enum, showing successful conversion and error handling with `Result`. ```rust let dow = DayOfWeek::try_from_i32(5); println!("{dow:?}"); // prints: Ok(Friday) let dow = DayOfWeek::try_from_i32(50); println!("{dow:?}"); // prints: Err(50) ``` -------------------------------- ### Rust Property-like Accessors (Getters and Setters) Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/custom-types/members Demonstrates Rust's convention for implementing property-like accessor methods. Getters are named after the field, and setters use a `set_` prefix. This example also includes computed properties. ```rust struct Rectangle { x1: i32, y1: i32, x2: i32, y2: i32, } impl Rectangle { pub fn new(x1: i32, y1: i32, x2: i32, y2: i32) -> Self { Self { x1, y1, x2, y2 } } // like property getters (each shares the same name as the field) pub fn x1(&self) -> i32 { self.x1 } pub fn y1(&self) -> i32 { self.y1 } pub fn x2(&self) -> i32 { self.x2 } pub fn y2(&self) -> i32 { self.y2 } // like property setters pub fn set_x1(&mut self, val: i32) { self.x1 = val } pub fn set_y1(&mut self, val: i32) { self.y1 = val } pub fn set_x2(&mut self, val: i32) { self.x2 = val } pub fn set_y2(&mut self, val: i32) { self.y2 = val } // like computed properties pub fn length(&self) -> i32 { self.y2 - self.y1 } pub fn width(&self) -> i32 { self.x2 - self.x1 } pub fn area(&self) -> i32 { self.length() * self.width() } } ``` -------------------------------- ### Rust: Corrected Ownership and Move Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/memory-management/index A corrected version of the Rust ownership example. After moving ownership from 'a' to 'b', the code correctly accesses and prints the fields of the 'Point' struct using 'b'. Upon exiting the scope, the memory owned by 'b' is automatically dropped. ```rust fn main() { let a = Point { x: 12, y: 34 }; // point owned by a let b = a; // b owns the point now println!("{}, {}", b.x, b.y); // ok, uses b } // point behind b is dropped ``` -------------------------------- ### Rust Implicit Type Coercion (Subtyping) Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/conversion-and-casting Illustrates a valid implicit conversion in Rust using subtyping, specifically with string slices. It shows how a static string slice can be coerced into a lifetime-annotated slice. ```rust fn bar<'a>() { let s: &'static str = "hi"; let t: &'a str = s; } ``` -------------------------------- ### Rust Function Pointer and Closure Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/lambda-and-closures Demonstrates Rust's `fn` type for function pointers and closure expressions. The `do_twice` function accepts a function pointer and an integer, applying the function twice. The `main` function shows how to call `do_twice` with a closure expression. ```rust fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { f(arg) + f(arg) } fn main() { let answer = do_twice(|x| x + 1, 5); println!("The answer is: {}", answer); // Prints: The answer is: 12 } ``` -------------------------------- ### C# XML Documentation Comment Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/documentation-comments This snippet demonstrates how to use XML-based documentation comments in C# to document types. The C# compiler processes these comments to generate structured XML output that can be used by other tools for human-readable documentation. ```csharp /// /// This is a document comment for MyClass. /// public class MyClass {} ``` -------------------------------- ### Conditional Compilation with Rust `cfg` Attribute Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/conditional-compilation/index Shows how to use Rust's `cfg` attribute for conditional compilation based on configuration predicates. This example demonstrates including `Display` implementations based on OS type (`unix`) and custom configurations (`foo = "bar"`). Compilation requires specific `rustc` flags. ```rust use std::fmt::{Display, Formatter}; struct MyStruct; // This implementation of Display is only included when the OS is unix but foo is not equal to bar // You can compile an executable for this version, on linux, with 'rustc main.rs --cfg foo="baz"' #[cfg(all(unix, not(foo = "bar")))] impl Display for MyStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str("Running without foo=bar configuration") } } // This function is only included when both unix and foo=bar are defined // You can compile an executable for this version, on linux, with 'rustc main.rs --cfg foo="bar"' #[cfg(all(unix, foo = "bar"))] impl Display for MyStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str("Running with foo=bar configuration") } } // This function is panicking when not compiled for unix // You can compile an executable for this version, on windows, with 'rustc main.rs' #[cfg(not(unix))] impl Display for MyStruct { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { panic!() } } fn main() { println!("{}", MyStruct); } ``` -------------------------------- ### C# Database Connection Disposal with IDisposable Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Demonstrates how to manage a database connection in C# using the `IDisposable` interface. The `using` statement ensures that the `Dispose` method is called automatically when the scope ends, preventing resource leaks. This example uses a custom `DatabaseConnection` class that wraps a `SqlConnection`. ```csharp using System; using System.Data.SqlClient; // Assuming SqlConnection is used public class DatabaseConnection : IDisposable { readonly string connectionString; SqlConnection connection; // this implements IDisposable public DatabaseConnection(string connectionString) => this.connectionString = connectionString; public void Dispose() { // Making sure to dispose the SqlConnection if (this.connection != null) { this.connection.Dispose(); } Console.WriteLine($"Closing connection: {this.connectionString}"); } } public class Example { public static void Main(string[] args) { using var db1 = new DatabaseConnection("Server=A;Database=DB1"); using var db2 = new DatabaseConnection("Server=A;Database=DB2"); // ...code using "db1" and "db2"... } // "Dispose" of "db1" and "db2" called here; when their scope ends } ``` -------------------------------- ### Implementing Extension Methods in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/custom-types/members Demonstrates how to add new methods to existing types using C# extension methods and Rust traits. Both examples extend a string-like type to add a 'wrap' functionality. C# requires importing the namespace, while Rust requires importing the trait. ```csharp using System; using System.Text; using Extensions; // (1) var sb = new StringBuilder("Hello, World!"); sb.Wrap(">>> ", " <<<"); // (2) Console.WriteLine(sb.ToString()); // Prints: >>> Hello, World! <<< namespace Extensions { static class StringBuilderExtensions { public static void Wrap(this StringBuilder sb, string left, string right) => sb.Insert(0, left).Append(right); } } ``` ```rust #![allow(dead_code)] mod exts { pub trait StrWrapExt { fn wrap(&mut self, left: &str, right: &str); } impl StrWrapExt for String { fn wrap(&mut self, left: &str, right: &str) { self.insert_str(0, left); self.push_str(right); } } } fn main() { use exts::StrWrapExt as _; let mut s = String::from("Hello, World!"); s.wrap(">>> ", " <<<"); // (2) println!("{s}"); // Prints: >>> Hello, World! <<< } ``` -------------------------------- ### Conditional Compilation with Rust cfg Attributes Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Illustrates Rust's cfg attribute for conditional compilation based on configuration predicates. The example shows how to conditionally implement the Display trait for a struct based on OS and custom configurations like 'foo'. Compilation requires specific rustc flags. ```rust use std::fmt::{Display, Formatter}; struct MyStruct; // This implementation of Display is only included when the OS is unix but foo is not equal to bar // You can compile an executable for this version, on linux, with 'rustc main.rs --cfg foo="baz"' #[cfg(all(unix, not(foo = "bar")))] impl Display for MyStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str("Running without foo=bar configuration") } } // This function is only included when both unix and foo=bar are defined // You can compile an executable for this version, on linux, with 'rustc main.rs --cfg foo="bar"' #[cfg(all(unix, foo = "bar"))] impl Display for MyStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str("Running with foo=bar configuration") } } // This function is panicking when not compiled for unix // You can compile an executable for this version, on windows, with 'rustc main.rs' #[cfg(not(unix))] impl Display for MyStruct { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { panic!() } } fn main() { println!("{}", MyStruct); } ``` -------------------------------- ### Rust: Iterator Chain Equivalent to C# LINQ Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/linq/index This Rust code snippet mirrors the C# LINQ example by using iterator adapters. It generates a range, filters for even numbers, uses `flat_map` to create nested ranges, and `fold` to calculate the sum, demonstrating Rust's functional approach to data transformation. ```rust let result = (0..10) .filter(|x| x % 2 == 0) .flat_map(|x| (0..x)) .fold(0, |acc, x| acc + x); println!("{result}"); // 50 ``` -------------------------------- ### Rust Doc Comment Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/documentation-comments This snippet shows the equivalent of C# documentation comments in Rust. Rust uses Markdown syntax for its doc comments, which are compiled into documentation by `rustdoc`, typically invoked using `cargo doc`. ```rust /// This is a doc comment for `MyStruct`. struct MyStruct; ``` -------------------------------- ### Rust: Ownership and Move Semantics Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/memory-management/index Demonstrates Rust's ownership concept where a variable 'a' initially owns a 'Point' struct. Ownership is then moved to 'b', rendering 'a' invalid. Attempting to access 'a' after the move results in a compile-time error. ```rust #![allow(dead_code, unused_variables)] struct Point { x: i32, y: i32, } fn main() { let a = Point { x: 12, y: 34 }; // point owned by a let b = a; // b owns the point now println!("{}, {}", a.x, a.y); // compiler error! } ``` -------------------------------- ### Rust: Mutable and Immutable Methods with `self` Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/custom-types/members Demonstrates how Rust expresses mutability in methods using the `self` parameter. Immutable methods take `&self`, while mutable methods take `&mut self`. This example defines a `Point` struct and methods to access and modify its coordinates. ```rust struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Self { x, y } } // self is not mutable pub fn x(&self) -> i32 { self.x } pub fn y(&self) -> i32 { self.y } // self is mutable pub fn set_x(&mut self, val: i32) { self.x = val } pub fn set_y(&mut self, val: i32) { self.y = val } } ``` -------------------------------- ### User-Defined Type Conversions with From/Into Trait in Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Explains Rust's `From` and `Into` traits for user-defined type conversions, analogous to C#'s conversion operators. Implementing `From` automatically provides `Into`. The example shows converting a string slice to a `String` and a custom `MyId` type to a `String`. ```rust fn main() { let my_id = MyId("id".into()); // `into()` is implemented automatically due to the `From<&str>` trait implementation for `String`. println!("{}", String::from(my_id)); // This uses the `From` implementation for `String`. } struct MyId(String); impl From for String { fn from(MyId(value): MyId) -> Self { value } } ``` -------------------------------- ### Constrained Generic Types in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Illustrates how to constrain generic types using the 'where' clause in C# and bounds in Rust. This ensures that generic type parameters meet specific requirements, such as implementing certain traits or interfaces. The C# example explicitly implements IEquatable, while the Rust version conditionally implements PartialEq. ```csharp using System; // Note: records automatically implement `IEquatable`. The following // implementation shows this explicitly for a comparison to Rust. sealed record Timestamped(DateTime Timestamp, T Value) : IEquatable> where T : IEquatable { public Timestamped(T value) : this(DateTime.UtcNow, value) { } public bool Equals(Timestamped? other) => other is { } someOther && Timestamp == someOther.Timestamp && Value.Equals(someOther.Value); public override int GetHashCode() => HashCode.Combine(Timestamp, Value); } ``` ```rust use std::time::*; struct Timestamped { value: T, timestamp: SystemTime } impl Timestamped { fn new(value: T) -> Self { Self { value, timestamp: SystemTime::now() } } } impl PartialEq for Timestamped where T: PartialEq { fn eq(&self, other: &Self) -> bool { self.value == other.value && self.timestamp == other.timestamp } } ``` -------------------------------- ### .NET: Configuration with Environment Variables Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print This .NET code demonstrates how to configure an application using environment variables via the `Microsoft.Extensions.Configuration` namespace. It uses `ConfigurationBuilder` to add environment variables as a configuration source and retrieves a value using `GetValue`. This approach allows for flexible configuration based on the environment. ```.NET using Microsoft.Extensions.Configuration; class Example { static void Main() { IConfiguration configuration = new ConfigurationBuilder() .AddEnvironmentVariables() .Build(); var example = configuration.GetValue("ExampleVar"); Console.WriteLine(example); } } ``` -------------------------------- ### Manage application configuration in C# and Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/environment-and-configuration/index This section demonstrates how to handle application configuration in both C# and Rust, often sourcing from environment variables. C# utilizes the `Microsoft.Extensions.Configuration` framework with `IConfiguration` and `AddEnvironmentVariables`, while Rust typically relies on third-party crates like `config` to build and retrieve configuration values from various sources. ```C# using Microsoft.Extensions.Configuration; class Example { static void Main() { IConfiguration configuration = new ConfigurationBuilder() .AddEnvironmentVariables() .Build(); var example = configuration.GetValue("ExampleVar"); Console.WriteLine(example); } } ``` ```Rust use config::{Config, Environment}; fn main() { let builder = Config::builder().add_source(Environment::default()); match builder.build() { Ok(config) => { match config.get_string("examplevar") { Ok(v) => println!("{v}"), Err(e) => println!("{e}") } }, Err(_) => { // something went wrong } } } ``` -------------------------------- ### C# Type Constants Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print In C#, constants of a type are typically declared as static read-only fields, as shown in this example for a Point record struct. ```csharp readonly record struct Point(int X, int Y) { public static readonly Point Zero = new(0, 0); } ``` -------------------------------- ### Rust: Configuration with Third-Party Crates Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print This Rust code snippet shows how to use the `config` crate to read configuration from environment variables. It builds a configuration using `Config::builder`, adds an environment source, and retrieves a string value. This demonstrates a common pattern for managing application configuration in Rust. ```Rust use config::{Config, Environment}; fn main() { let builder = Config::builder().add_source(Environment::default()); match builder.build() { Ok(config) => { match config.get_string("examplevar") { Ok(v) => println!("{v}"), Err(e) => println!("{e}") } }, Err(_) => { // something went wrong } } } ``` -------------------------------- ### Rust Enum as Discriminated Union Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/custom-types/enums Shows how Rust enums can be used to define discriminated union types, where each variant can hold data specific to it. Includes examples of creating instances. ```rust enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from("::1")); ``` -------------------------------- ### Add NuGet Package (.NET CLI) Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Demonstrates how to add a NuGet package dependency to a .NET project using the `dotnet add package` command. This command modifies the project file to include the specified package reference. ```bash dotnet add package morelinq ``` -------------------------------- ### Pattern Matching Optional Values in Rust with if let Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Shows a more concise way to handle `Option` in Rust using `if let` for pattern matching. ```rust let max = Some(10u32); if let Some(max) = max { println!("The maximum is {}.", max); } ``` -------------------------------- ### Adding Dependencies: .NET CLI vs. Cargo CLI Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/compilation-and-building/index Demonstrates how to add external packages to a project using the .NET CLI's `dotnet add package` command and Rust's Cargo CLI's `cargo add` command. ```bash dotnet add package morelinq ``` ```bash cargo add tokio ``` -------------------------------- ### Rust iteration over Vec consuming elements Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/linq/index Demonstrates iterating over a Rust `Vec` where ownership of elements is consumed by the loop. This example highlights potential compilation errors when attempting to iterate over the same `Vec` multiple times due to moved values. ```rust fn main() { let values = vec![1, 2, 3, 4, 5]; // sum all values let mut sum = 0; for value in values { sum += value; } println!("sum = {sum}"); // determine maximum value let mut max = None; for value in values { if let Some(some_max) = max { // if max is defined if value > some_max { // and value is greater max = Some(value) // then note that new max } } else { // max is undefined when iteration starts max = Some(value) // so set it to the first value } } println!("max = {max:?}"); } ``` -------------------------------- ### Thread-Safe Data Increment in C#/.NET Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/threading/synchronization Demonstrates incrementing a shared variable across multiple threads using C#'s `lock` keyword for synchronization. This example requires the `System.Threading` namespace. ```csharp using System; using System.Threading; var dataLock = new object(); var data = 0; var threads = new List(); for (var i = 0; i < 10; i++) { var thread = new Thread(() => { for (var j = 0; j < 1000; j++) { lock (dataLock) data++; } }); threads.Add(thread); thread.Start(); } foreach (var thread in threads) thread.Join(); Console.WriteLine(data); ``` -------------------------------- ### Pattern Matching Optional Values in Rust with match Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Illustrates how to use `match` statements in Rust for pattern matching on `Option` values, similar to C# nullable checks. ```rust let max = Some(10u32); match max { Some(max) => println!("The maximum is {}.", max), // The maximum is 10. None => () // Do nothing if None } ``` -------------------------------- ### Controlling Flow with Nullable Values in C# Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print Demonstrates using `if`/`else` statements and pattern matching in C# to handle nullable values. ```csharp uint? max = 10; if (max is { } someMax) { Console.WriteLine($"The maximum is {someMax}."); // The maximum is 10. } ``` -------------------------------- ### C# Implicit Type Conversion Example Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/language/conversion-and-casting Demonstrates implicit type conversion in C#, where a smaller integer type (int) is automatically converted to a larger one (long). This is allowed due to the absence of data loss. ```csharp int intNumber = 1; long longNumber = intNumber; ``` -------------------------------- ### Run Clippy with Warnings as Errors in Rust Source: https://microsoft.github.io/rust-for-dotnet-devs/latest/print This command runs Clippy, Rust's linter, and treats all warnings as errors, similar to how .NET's `TreatWarningsAsErrors` setting works. This ensures code quality by failing the build if any warnings are detected. ```bash cargo clippy -- -D warnings ```