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