I always forget these so here is a note so that I can look them up easily. You can get the default newline charaters for the current system using the "Environment.NewLine".
Carriage Return (CR, '\r', ASCII 13): A Carriage return, takes the paper carriage back to the beginning of the line. In computing this control character repositions the cursor to the beginning of the line without going down to the next line.
Line Feed (LF, '\n', ASCII 10): In a typewriter, the line feed will help advance the paper by one line. In computing, this tip moves the cursor down to the next line without going back to the start of the line again.
On Windows it is Carriage return, Line feed or "\r\n"
I believe Linux and Unix and Mac OS (?) use "\n"
R. Bovills .NET Blog
.NET Tricks, Tips, and Snippets
August 21, 2026
Carriage Return and Line Feed
June 9, 2026
Windows Extended Length Path
The \\?\ (pronounced “extended-length path” or “verbatim path”) syntax is a Windows path prefix that tells the system to treat the path literally and bypass normal Windows path processing (path normalization, MAX_PATH length limit, and some path parsing rules). Key points:
Purpose
- Allows paths longer than MAX_PATH (260 characters).
- Prevents the system from interpreting backslashes, relative segments (., ..), or expanding device names; the path is taken verbatim.
Syntax
- For local paths: start with \\?\ followed immediately by a drive letter and a colon, e.g.: \\?\C:\very\long\path...
- For UNC/network paths: use the \\?\UNC\ form instead of \\server\share, e.g.: \\?\UNC\server\share\path...
- Do not mix forward slashes; use backslashes.
Limits and behavior
- Removes the MAX_PATH ~260-character limit for most APIs that accept Win32 file paths when used with wide-char (UTF-16) APIs.
- Some Win32 APIs, shells, and libraries do not accept \\?\ paths; some higher-level frameworks (older .NET, Windows Explorer) may not handle them.
- Certain parse rules are disabled: the path is not normalized (so trailing dots/spaces are preserved) and long relative components won’t be collapsed.
- You must use absolute paths; relative paths with \\?\ are not supported.
- For device paths (NT namespace) a different prefix \\?\GLOBALROOT\ or \\.\ may be used for special device access.
Unicode
- Typically used with wide-character (W) Win32 APIs (UTF-16). Passing UTF-8/ANSI APIs can be problematic.
Examples
- Long local path: \\?\C:\very\long\directory... ( > 260 chars )
- Long UNC path: \\?\UNC\myserver\myshare\folder\file.txt
Common pitfalls
- Some Windows APIs (including many shell APIs) reject \\?\ paths.
- Don’t use trailing backslash immediately after \\?, e.g., \\?\C:\ is fine but be careful with extra slashes.
- When interop with libraries/frameworks, strip or add the prefix only at the last moment when calling Win32 functions.
C# example — using the \\?\ (verbatim/extended-length) path prefix
using System;
using System.IO;
using System.Text;
class Program
{
// Helper: convert a normal absolute path to an extended-length path for local drive or UNC
static string ToExtendedLengthPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentException(nameof(path));
// Normalize separators
path = Path.GetFullPath(path);
// If UNC path (\\server\share\...), convert to \\?\UNC\server\share\...
if (path.StartsWith(@"\\"))
{
return @"\\?\UNC\" + path.Substring(2);
}
// Otherwise (drive letter) prefix with \\?\
return @"\\?\" + path;
}
static void Main()
{
// Example long folder path (ensure this exists or create it)
string longFolder = @"C:\example\very\long\path\that\..."; // replace with real long path
string extended = ToExtendedLengthPath(longFolder);
Console.WriteLine("Extended path: " + extended);
// Create directory using extended path
Directory.CreateDirectory(extended);
Console.WriteLine("Directory created.");
// Create a file inside that directory
string file = Path.Combine(extended, "test.txt");
using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))
using (var sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.WriteLine("Hello from extended-length path!");
}
Console.WriteLine("File written.");
// Read the file back
using (var sr = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read), Encoding.UTF8))
{
Console.WriteLine("File contents:");
Console.WriteLine(sr.ReadToEnd());
}
}
}
Notes:
- Use Path.GetFullPath to ensure an absolute path before adding the prefix.
- For UNC paths (start with \\), convert to \\?\UNC... as shown.
- Many .NET APIs work with \\?\ paths on modern runtimes, but some higher-level APIs or components (older frameworks, Windows shell) may not.
June 8, 2026
Datasets in Html and Javascript
<button data-sandwich="tuna" data-topping="tomato" data-snack="cookies">Place Order</button>
Here is the Javascript to access the dataset on the button:
let btn = document.querySelector('button');
let dataset = btn.dataset; // Access "data-" attributes here
console.log("All dataset attributes: ");
console.log(dataset);
let sandwich = btn.dataset.sandwich; // Access individually as properties of "dataset"
console.log("sandwich=" + sandwich);
let {topping, snack} = btn.dataset; // Access using tuples
console.log(sandwich, topping, snack);
let snack2 = btn.dataset["snack"]; // Access the properties dynamically
console.log("snack2=" + snack);
btn.dataset.side = 'chips'; // Add more dataset attributes
console.log(dataset);
console.log("All done");
The code can be accessed here: https://codepen.io/capitanacerimmer/pen/JobbWYa?editors=1111Note that the console output is not activated by the button itself
March 30, 2026
C# Compiler "CallerArgumentExpression"
Here is an example usage of the "CallerArgumentExpression". It allows you to capture a copy of some compiled code that evaluates to a value expression
void Main()
{
var x = 34;
var y = 23;
Assert.That(x > y, $"{x} > {y}");
x = 20;
Assert.That(x > y, $"{x} > {y}");
}
// You can define other methods, fields, classes and namespaces here
public static class Assert
{
public static void That(
bool condition,
string message = "",
[CallerArgumentExpression("condition")] string expression = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
if (!condition)
{
var fullMsg = $"{sourceFilePath}:{sourceLineNumber} {memberName} - Assertion \"{expression}\" evaluated to FALSE: {message}";
Trace.WriteLine(fullMsg);
Console.WriteLine(fullMsg);
}
}
}
In this case the expression "x > y" that is passed in as the value of "bool condition" parameter is inserted by the compiler into the "string expression" parameter. In this example, the first Assert passes and outputs nothing but the second one outputs the following:
C:\...\Temp\LINQPad8\_hxysxhku\ewejlm\LINQPadQuery:7 Main - Assertion "x > y" evaluated to FALSE: 20 > 23
February 26, 2026
Functional Programming & Monads in C#
🧠 Introduction
Functional programming (FP) is a paradigm focused on pure functions, immutability, and composable transformations. Modern C# supports many FP concepts, making it possible to write expressive, predictable, and safe code without leaving the .NET ecosystem. This guide walks through the core FP ideas, monads, immutability, partial functions, and practical C# examples — all in clean Markdown for your blog.
1. Core Concepts of Functional Programming (FP)
1.1 First-Class & Higher-Order Functions
In FP:
- Functions are treated as values: you can pass them around, store them in variables, and return them from other functions.
- Higher-order functions take other functions as parameters or return them.
Example:
Func<int, int, int> add = (x, y) => x + y;
// Higher-order function: takes a function as input
int ApplyOperation(int a, int b, Func<int, int, int> operation)
{
return operation(a, b);
}
var result = ApplyOperation(5, 3, add); // result = 8
1.2 Immutability
- FP emphasizes immutable data, once created, values don’t change.
- In C#, you can use readonly fields, record types, or avoid mutating collections
- Data does not change after creation. Instead, you create new values.
Example using records:
record Person(string Name, int Age);
...
var p1 = new Person("Isabel", 30);
// Instead of mutating, create a new instance
var p2 = p1 with { Age = 31 }; // p2 is a new object
1.3 Pure Functions
- A pure function always returns the same output for the same input and has no side effects (like modifying global state or I/O).
- This makes code predictable and testable.
Pure:
int Square(int x) => x * x; // Pure function
Not pure:
int counter = 0;
int Increment() => ++counter; // Not pure (depends on external state)
1.4 Function Composition
Combine small functions into larger ones.
Func<int, int> doubleIt = x => x * 2;
Func<int, int> squareIt = x => x * x;
// Compose manually
Func<int, int> doubleThenSquare = x => squareIt(doubleIt(x));
var result = doubleThenSquare(3); // (3*2)^2 = 36
1.5 Declarative Style (LINQ)
- FP favors describing what to do rather than how to do it.
- LINQ is a great example of declarative programming in C#.
var numbers = new[] { 1, 2, 3, 4, 5 };
// Declarative: filter and transform
var evensSquared = numbers
.Where(n => n % 2 == 0)
.Select(n => n * n);
foreach (var n in evensSquared)
Console.WriteLine(n); // Output: 4, 16
1.6 Lazy Evaluation
- FP often defers computation until needed.
- In C#, IEnumerable
with yield return or LINQ queries are (mostly) lazily evaluated.
IEnumerable<int> Squares()
{
int i = 1;
while (true)
yield return i * i++;
}
🔑 Summary Functional programming in C# revolves around:
- Treating functions as values
- Using immutability
- Writing pure functions
- Composing small functions
- Favoring declarative style (LINQ)
- Leveraging lazy evaluation
2. Monads in C#
2.1 What Is a Monad?
A monad is a design pattern from functional programming that:
- Wraps a value in a context (e.g., "maybe this value exists", "this value is asynchronous", "this value is a sequence").
- Provides a way to chain operations on that value without breaking the context.
- Ensures consistent handling of side effects (nulls, errors, async, logging, etc.). Think of it as a container + rules for chaining.
A monad must support:
- Return/Unit → wrap a value (handle the cases where the function has no valid value, eg null pointer, ...)
- Bind → Chain operations (so it can be chained through functions) and everything works even if the value is null/none/invalid, etc. This works because we make functions act like pure functions by handling the bad cases through the Monad.
2.2 Common Monads in C#
| Monad | Meaning |
|---|---|
| Task<T> | Asynchronous computation |
| IEnumerable<T> | Sequence computation |
| Nullable<T> | Optional values |
| Result<T> | Success/failure pipeline |
2.3.1 Example: Option Monad
/// <summary>
/// An option type that represents a value that may or may not be present.
/// It is used to avoid null references and provide a safer way to handle optional values.
/// </summary>
/// <typeparam name="T"></typeparam>
public class Option<T>
{
private readonly T _value;
/// <summary>
/// Gets a value indicating whether the current Option has a value.
/// </summary>
public bool HasValue { get; }
// Private constructor to create an Option with a value or without a value
private Option() { HasValue = false; }
// Private constructor to create an Option with a value
private Option(T value) { _value = value; HasValue = true; }
/// </summary>
/// Factory methods to create an Option with a <paramref name="value"/>
/// </summary>
/// <param name="value">The value to wrap in an Option.</param>
/// <returns>An Option containing the specified value.</returns>
public static Option<T> Some(T value) => new(value);
/// <summary>
/// Factory methods to create an Option without a value
/// </summary>
/// <returns>An empty Option.</returns>
public static Option<T> None() => new();
/// <summary>
/// Invokes f with the current value when present and returns the resulting Option; otherwise returns None. Like SelectMany in LINQ.
/// </summary>
/// <remarks>Implements monadic bind (flatMap) semantics for Option<T>. Allows for chaining operations that might fail.</remarks>
/// <typeparam name="TResult">The type of the value contained in the returned Option.</typeparam>
/// <param name="f">Function that maps the current value to an Option<TResult>.</param>
/// <returns>An Option<TResult> produced by applying f to the current value if present; otherwise a None Option<TResult>.</returns>
public Option<TResult> Bind<TResult>(Func<T, Option<TResult>> f)
=> HasValue ? f(_value) : Option<TResult>.None();
/// <summary>
/// Maps the current value to a new value of type TResult if present; otherwise returns None. (like Select in LINQ)
/// </summary>
/// <remarks>Implements monadic map semantics for Option<T>.</remarks>
/// <typeparam name="TResult">The type of the value contained in the returned Option.</typeparam>
/// <param name="f">Function that maps the current value to a TResult.</param>
/// <returns>An Option<TResult> containing the mapped value if present; otherwise a None Option<TResult>.</returns>
public Option<TResult> Map<TResult>(Func<T, TResult> f)
=> HasValue ? Option<TResult>.Some(f(_value)) : Option<TResult>.None();
/// <summary>
/// Extract the value with a fallback/default if the current Option is None.
/// </summary>
/// <param name="fallback">The value to return if the current Option is None.</param>
/// <returns>The current value if present; otherwise the fallback value.</returns>
public T GetValueOrDefault(T fallback)
=> HasValue ? _value : fallback;
}
2.3.2 Using this Monad
var maybeNumber = Option<int>.Some(5);
var result = maybeNumber
.Bind(x => Option<int>.Some(x * 2))
.Bind(x => Option<int>.Some(x + 10));
// result = Some(20)
This avoids null checks everywhere — the monad handles the "no value" case.
2.4.1 Task Monad (async) Example
Task
- Task.FromResult(value) → wraps a value.
- await / ContinueWith → bind operations.
async Task<int> DoubleAsync(int x) => x * 2;
var result = await Task.FromResult(5)
.ContinueWith(t => DoubleAsync(t.Result))
.Unwrap();
Here Task ensures async chaining without manually handling threads.
2.5.1 LINQ Query Syntax (Enumerable Monad)
LINQ’s SelectMany is the bind operation for sequences.
var numbers = new[] { 1, 2, 3 };
var doubled = from n in numbers
from m in new[] { n * 2 }
select m;
// doubled = {2, 4, 6}
LINQ query comprehension is syntactic sugar for monadic chaining.
⚡ Summary In C#:
- Option
(or Nullable ) → Maybe Monad - Task
→ Async Monad - IEnumerable
→ Sequence Monad - LINQ query syntax → Monadic chaining (SelectMany) 👉 The purpose: monads let you build pipelines of computation while hiding the messy details of context management (nulls, async, errors, etc.).
🧩 Scenario Imagine a WPF app where the ViewModel fetches a user profile. Sometimes the profile data might be missing (e.g., network error, no record). Instead of sprinkling if (profile != null) everywhere, we’ll use an Option Monad.
- Define a Simple Option<T> Monad. See the class above
3. Monads in MVVM (Practical Example)
public class ProfileViewModel : ObservableObject
{
private Option<UserProfile> _profile = Option<UserProfile>.None();
public string DisplayName =>
_profile.Map(p => $"Welcome, {p.Name}!").GetValueOrDefault("Guest");
public async Task LoadAsync()
{
var fetched = await FetchProfileAsync();
_profile = fetched is null
? Option<UserProfile>.None()
: Option<UserProfile>.Some(fetched);
OnPropertyChanged(nameof(DisplayName));
}
}
4. Partial Functions
4.1 What Is a Partial Function?
A function that is not defined for all inputs. Example:
int Divide(int x, int y) => x / y; // undefined when y ** 0
4.2 Partial Application (Different Concept)
Fixing some arguments of a function.
Func<int, int, int> add = (x, y) => x + y;
Func<int, int> addFive = y => add(5, y);
4.3 Lifting a Partial Function into a Monad
Option<int> SafeDivide(int x, int y)
{
if (y == 0) return Option<int>.None();
return Option<int>.Some(x / y);
}
6. Immutability in Functional Programming
6.1 Why It Matters
Immutability provides:
- predictability
- pure functions
- thread safety
- referential transparency
- easier debugging
- safe composition
- undo/redo and time-travel debugging
6.2 Example: Immutable State
record AppState(int Count);
var state1 = new AppState(0);
var state2 = state1 with { Count = state1.Count + 1 };
7. Using Monads for Unit-Safe Values
7.1 Example: Length Monad
public class Length
{
private readonly double _meters;
private Length(double meters) => _meters = meters;
public static Length FromMeters(double m) => new(m);
public static Length FromKilometers(double km) => new(km * 1000);
public Length Map(Func<double, double> f) => new(f(_meters));
public Length Bind(Func<double, Length> f) => f(_meters);
public double ToMeters() => _meters;
}
8. Practice Quiz (Optional)
1. What is a pure function?
Answer: A function with no side effects that always returns the same output for the same input.
2. Which LINQ method corresponds to monadic bind?
Answer: Select Many
3. What is the purpose of a monad?
Answer: To wrap values in context and allow safe, composable operations.
4. Which C# type is an example of a monad?
Answer: Task
5. How does Option help in MVVM?
Answer: Eliminates null checks by encapsulating optional values.
9. Summary
Functional programming in C# gives you:
- safer code
- predictable behavior
- composable pipelines
- easier testing
- fewer bugs
Monads, immutability, and pure functions work together to create a clean, expressive, and maintainable architecture.
February 17, 2026
From ".slnx" => ".sln" file
To create a new ".slnx" solution file from a ".sln" file. Open a command window (cmd.exe). Within that window change to the folder containing your "{YourSolutionName}.sln" file, you can do this with "cd <solution folder path>". Now, type in the following line:
"dotnet sln {YourSolutionName}.sln migrate"
This generates a new "{YourSolutionName}.slnx" file. The original "{YourSolutionName}.sln" file remains untouched. Here is an example of an slnx file:
<Solution>
<Configurations>
<Platform Name="Any CPU" />
<Platform Name="x86" />
</Configurations>
<Project Path="../Car.Utilities.Common/Car.Utilities.Common.NUnit/Car.Utilities.Common.NUnit.csproj" />
<Project Path="../Car.Utilities.Common/Car.Utilities.Common/Car.Utilities.Common.csproj" />
<Project Path="MyProject.UnitTests/MyProject.UnitTests.csproj" />
<Project Path="MyProject/MyProject.csproj" />
</Solution>
It is quite simple and can be code genereated quite easily
February 6, 2026
C# Dot Net SDK Version Macros
1. Use "#if" with framework version symbols to include specific code for specific .Net versions .NET SDK defines symbols like "Net5_0", "Net6_0", "Net7_0", etc. For .NET 10, the symbol will be "Net10_0". This works automatically if you're targeting .NET 10 via the SDK-style project and using the element <TargetFramework> like: "<TargetFramework>net10.0<TargetFramework>". Here is an example of this:
#if NET10_0
// This code will be included when targeting .NET 10
Console.WriteLine("Running on a framework other than .NET 10");
#endif
🧠 These symbols can be combined for example:
#if NET6_0 || NET7_0
Console.WriteLine("Running on .NET 6 or 7");
#elif NET10_0
Console.WriteLine("Running on .NET 10");
#endif
2. Invert the macro condition to exclude code using the ! sign
For example, you can use "#if !NET10_0" to exclude code when the target is not .NET 10.
Here is an example of this:
#if !NET10_0
// This code will be excluded when targeting .NET 10
Console.WriteLine("Running on a framework other than .NET 10");
#endif
3. You can also use a "_OR_GREATER" suffix, for example:
#if NET5_0_OR_GREATER
// This code will be included when targeting .NET 5 or greater
#endif
There are also platform-specific preprocessor symbols for conditional compilation based on the operating system. These are especially useful when writing cross-platform code in .NET Core or .NET 5+.
🧭 Built-in platform symbols
Here are the most common ones:
| OS | Target |
|---|---|
| WINDOWS | Compiling for Windows |
| LINUX | Compiling for Linux |
| OSX | Compiling for Mac OS |
| ANDROID | Compiling for Android |
| IOS | Compiling for iOS |
| MACCATALYST | Compiling for Mac Catalyst |
| FREEBSD | Compiling for FreeBSD |
| BROWSER | Compiling for WebAssembly (Blazor) |
✅ Example usage
#if WINDOWS
Console.WriteLine("Running on Windows");
#elif LINUX
Console.WriteLine("Running on Linux");
#elif OSX
Console.WriteLine("Running on macOS");
#else
Console.WriteLine("Unknown platform");
#endif
🔍 Notes
- These symbols are only defined when the runtime identifier (RID) or target platform is specified appropriately in your ".csproj " file.
- If you're multi-targeting or using runtime checks, you might prefer OperatingSystem.IsWindows() or similar APIs from System.Runtime.InteropServices
Note that this is heavily edited output from CoPilot.