Environment and Configuration
Accessing environment variables
.NET provides access to environment variables via the
System.Environment.GetEnvironmentVariable method. This method retrieves the
value of an environment variable at runtime.
using System;
const string name = "EXAMPLE_VARIABLE";
var value = Environment.GetEnvironmentVariable(name);
if (string.IsNullOrEmpty(value))
Console.WriteLine($"Variable '{name}' not set.");
else
Console.WriteLine($"Variable '{name}' set to '{value}'.");
Rust provides the same environment variable access functionality at
runtime via the var and var_os functions from the std::env module.
The var function will return a Result<String, VarError>, and either returns the
variable if it is set or returns an error if the variable is either not set or is not
valid Unicode.
var_os has a different signature giving back an Option<OsString>, either
returning some value if the variable is set, or returning None if the variable
is not set. An OsString is not required to be valid Unicode.
use std::env;
fn main() {
let key = "ExampleVariable";
match env::var(key) {
Ok(val) => println!("{key}: {val:?}"),
Err(e) => println!("couldn't interpret {key}: {e}"),
}
}
use std::env;
fn main() {
let key = "ExampleVariable";
match env::var_os(key) {
Some(val) => println!("{key}: {val:?}"),
None => println!("{key} not defined in the enviroment"),
}
}
Rust also provides environment variable access functionality at
compile time. The env! macro from std::env expands the value of the variable
at compile time, returning a &'static str. If the variable is not set, an
error is emitted.
use std::env;
fn main() {
let example = env!("ExampleVariable");
println!("{example}");
}
In .NET compile time access to environment variables can be achieved, albeit in a less straightforward way, via source generators.
Configuration
Configuration in .NET is possible with configuration providers. The framework
provides several provider implementations via
Microsoft.Extensions.Configuration namespace and NuGet packages.
Configuration providers read configuration data from key-value pairs using
different sources and provide a unified view of the configuration via the
IConfiguration type.
using Microsoft.Extensions.Configuration;
class Example {
static void Main()
{
IConfiguration configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var example = configuration.GetValue<string>("ExampleVar");
Console.WriteLine(example);
}
}
Other provider examples can be found in the official documentation Configurations provider in .NET.
A similar configuration experience in Rust is available via use of third-party crates such as figment or config.
See the following example making use of config crate:
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
}
}
}