<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>C# Code Examples by Khalid Abuhakmeh</title><description>Short, runnable C# and .NET code examples with output from Khalid Abuhakmeh.</description><link>https://khalidabuhakmeh.com/</link><item><title>Switch expressions — Tip #010</title><link>https://khalidabuhakmeh.com/tips/switch-expressions/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/switch-expressions/</guid><description>A switch expression returns a value directly, with no case labels or temp variable.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A switch expression returns a value directly, with no case labels or temp variable.&lt;/p&gt;&lt;p&gt;A switch expression returns a value directly, with no case labels or temp variable. Pattern match with a switch expression: every arm returns a value, and _ catches the rest. It is available since C# 8. The key line is `Species.Cat =&amp;gt; &quot;Purrr...&quot;` in `switch.cs`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;foreach (var species in Enum.GetValues&amp;lt;Species&amp;gt;())
{
    Console.WriteLine(species switch
    {
        Species.Cat =&amp;gt; &quot;Purrr...&quot;,
        Species.Dog =&amp;gt; &quot;Woof!&quot;,
        _ =&amp;gt; &quot;*Cthulhu noises*&quot;,
    });
}

enum Species { Unknown, Cat, Dog }&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;*Cthulhu noises*
Purrr...
Woof!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-010-switch-expressions.CQwFNOTB_Z2dW1z5.jpg&quot; alt=&quot;Code card: Switch expressions. Program output: *Cthulhu noises* / Purrr... / Woof!&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Sum per group with AggregateBy — Tip #009</title><link>https://khalidabuhakmeh.com/tips/linq-groupby-sum/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/linq-groupby-sum/</guid><description>AggregateBy groups and aggregates in one pass. No GroupBy + Select + Sum pipeline.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;AggregateBy groups and aggregates in one pass. No GroupBy + Select + Sum pipeline.&lt;/p&gt;&lt;p&gt;AggregateBy groups and aggregates in one pass. No GroupBy + Select + Sum pipeline. Total weight per species without GroupBy().Select(Sum): .NET 9 AggregateBy groups and folds in one pass. It is available since .NET 9. The key line is `var totals = pets.AggregateBy(` in `aggregateby.cs`. Run it and the output reads `Cat: 35, Dog: 259`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Pet[] pets = [
    new(Species.Cat, 20), new(Species.Dog, 60),
    new(Species.Dog, 199), new(Species.Cat, 15),
];

var totals = pets.AggregateBy(
    p =&amp;gt; p.Species, 0, (sum, p) =&amp;gt; sum + p.Weight);

foreach (var (species, weight) in totals)
    Console.WriteLine($&quot;{species}: {weight}&quot;);

record Pet(Species Species, int Weight = 0);
enum Species { Unknown, Cat, Dog }&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Cat: 35
Dog: 259&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-009-linq-groupby-sum.Cv-xG75I_Z1yYKQ6.jpg&quot; alt=&quot;Code card: Sum per group with AggregateBy. Program output: Cat: 35 / Dog: 259&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Culture-aware interpolation — Tip #008</title><link>https://khalidabuhakmeh.com/tips/format-specifiers/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/format-specifiers/</guid><description>FormattableString keeps the values and :C format for rendering with a chosen culture. The fr-FR result has a non-breaking space before €.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;FormattableString keeps the values and :C format for rendering with a chosen culture. The fr-FR result has a non-breaking space before €.&lt;/p&gt;&lt;p&gt;FormattableString keeps the values and :C format for rendering with a chosen culture. The fr-FR result has a non-breaking space before €. Interpolate once, format later: a FormattableString keeps the :C format so you render it with any CultureInfo. It is available since C# 6. The key line is `FormattableString text = $&quot;{price:C}&quot;` in `formats.cs`. Run it and the output reads `$100.00, 100,00 €`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;using System.Globalization;

var price = 100m;
FormattableString text = $&quot;{price:C}&quot;;

var usa = CultureInfo.GetCultureInfo(&quot;en-US&quot;);
var euro = CultureInfo.GetCultureInfo(&quot;fr-FR&quot;);

Console.WriteLine(text.ToString(usa));
Console.WriteLine(text.ToString(euro));&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;$100.00
100,00 €&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-008-format-specifiers.D2gdfUDu_Z1OjDM8.jpg&quot; alt=&quot;Code card: Culture-aware interpolation. Program output: $100.00 / 100,00 €&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Method groups in LINQ — Tip #007</title><link>https://khalidabuhakmeh.com/tips/linq-method-group/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/linq-method-group/</guid><description>When a lambda only forwards its argument, pass the method name. Same result, less noise.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When a lambda only forwards its argument, pass the method name. Same result, less noise.&lt;/p&gt;&lt;p&gt;When a lambda only forwards its argument, pass the method name. Same result, less noise. It is available since C# 2. The key line is `var verbose = cart.Select(x =&amp;gt; Display(x)).ToList()` in `methodgroup.cs`. Run it and the output reads `&amp;lt;APPLE&amp;gt;, &amp;lt;PEAR&amp;gt;, &amp;lt;FIG&amp;gt;, True`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;string[] cart = [&quot;apple&quot;, &quot;pear&quot;, &quot;fig&quot;];

var verbose = cart.Select(x =&amp;gt; Display(x)).ToList();
var concise = cart.Select(Display).ToList();

Console.WriteLine(string.Join(&quot;, &quot;, concise));
Console.WriteLine(verbose.SequenceEqual(concise));

static string Display(string s) =&amp;gt; $&quot;&amp;lt;{s.ToUpper()}&amp;gt;&quot;;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;APPLE&amp;gt;, &amp;lt;PEAR&amp;gt;, &amp;lt;FIG&amp;gt;
True&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-007-linq-method-group.D0iIhuvk_1rrwiN.jpg&quot; alt=&quot;Code card: Method groups in LINQ. Program output: &amp;lt;APPLE&amp;gt;, &amp;lt;PEAR&amp;gt;, &amp;lt;FIG&amp;gt; / True&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Chain lambdas on one delegate — Tip #006</title><link>https://khalidabuhakmeh.com/tips/lambda-chaining/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/lambda-chaining/</guid><description>Delegates are multicast: += chains lambdas and one call runs them all, in order.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Delegates are multicast: += chains lambdas and one call runs them all, in order.&lt;/p&gt;&lt;p&gt;Delegates are multicast: += chains lambdas and one call runs them all, in order. It is available since C# 3. The key line is `hello += () =&amp;gt; Console.Write(&quot;World, &quot;)` in `lambdas.cs`. Run it and the output reads `Hello World, .NET &amp;amp; Khalid`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Action hello = () =&amp;gt; Console.Write(&quot;Hello &quot;);
hello += () =&amp;gt; Console.Write(&quot;World, &quot;);
hello += () =&amp;gt; Console.WriteLine(&quot;.NET &amp;amp; Khalid&quot;);
hello();&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Hello World, .NET &amp;amp; Khalid&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-006-lambda-chaining.IFGK3YwW_Z2ixwCk.jpg&quot; alt=&quot;Code card: Chain lambdas on one delegate. Program output: Hello World, .NET &amp;amp; Khalid&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Union types in C# 15 — Tip #005</title><link>https://khalidabuhakmeh.com/tips/union-types-csharp-15/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/union-types-csharp-15/</guid><description>A union declares a closed set of case types. The compiler warns (CS8509) when a switch misses a case.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A union declares a closed set of case types. The compiler warns (CS8509) when a switch misses a case.&lt;/p&gt;&lt;p&gt;A union declares a closed set of case types. The compiler warns (CS8509) when a switch misses a case. C# 15 ships union types in .NET 11. Declare union Pet(Cat, Dog, Bird) and the compiler checks that your switch covers every case. Drop Bird and you get CS8509 &quot;&apos;Bird&apos; is not covered&quot;. Run it with the .NET 11 SDK. It is new in C# 15. The key line is `union Pet(Cat, Dog, Bird)` in `pets.cs`. Run it and the output reads `Rex says woof`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Pet pet = new Dog(&quot;Rex&quot;);
var sound = pet switch
{
    Cat c =&amp;gt; $&quot;{c.Name} says meow&quot;,
    Dog d =&amp;gt; $&quot;{d.Name} says woof&quot;,
    Bird b =&amp;gt; $&quot;{b.Name} says tweet&quot;,
};
Console.WriteLine(sound);

record Cat(string Name);
record Dog(string Name);
record Bird(string Name);
union Pet(Cat, Dog, Bird);&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Rex says woof&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-005-union-types-csharp-15.yvkGxnRK_Z2bsERo.jpg&quot; alt=&quot;Code card declaring a C# 15 Pet union of Cat, Dog and Bird, then switching on a Dog. Output: Rex says woof.&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Copy a record, change one thing — Tip #004</title><link>https://khalidabuhakmeh.com/tips/records-with-expression/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/records-with-expression/</guid><description>A with expression copies a record and changes only the properties you name. Records compare by value.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A with expression copies a record and changes only the properties you name. Records compare by value.&lt;/p&gt;&lt;p&gt;A with expression copies a record and changes only the properties you name. Records compare by value. It is available since C# 9. The key line is `var nicole = khalid with { Name = &quot;Nicole&quot; }` in `records.cs`. Run it and the output reads `Person { Name = Nicole, Planet = Earth }, False`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;var khalid = new Person(&quot;Khalid&quot;, &quot;Earth&quot;);
var nicole = khalid with { Name = &quot;Nicole&quot; };

Console.WriteLine(nicole);
Console.WriteLine(khalid == nicole);

record Person(string Name, string Planet);&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Person { Name = Nicole, Planet = Earth }
False&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-004-records-with-expression.BYSbqbG2_Z1M4mVn.jpg&quot; alt=&quot;Code card copying Khalid&apos;s Person record with Name changed to Nicole. The copy prints with Planet Earth and compares unequal to the original.&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Make big numbers readable — Tip #003</title><link>https://khalidabuhakmeh.com/tips/digit-separators/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/digit-separators/</guid><description>The compiler ignores underscores in numeric literals. They work in hex and binary too.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The compiler ignores underscores in numeric literals. They work in hex and binary too.&lt;/p&gt;&lt;p&gt;The compiler ignores underscores in numeric literals. They work in hex and binary too. How many zeroes? `1_000_000_000` vs `1000000000`. It is available since C# 7. The key line is `var easyBillion = 1_000_000_000` in `numbers.cs`. It fits in 12 lines; run it with `dotnet run numbers.cs`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;// how many zeroes is a billion?
var billion = 1000000000;

// oh! nine zeroes.
var easyBillion = 1_000_000_000;
Console.WriteLine(billion == easyBillion);

// works with hex and binary too
var color = 0xFF_EF_44_44;
var flags = 0b1010_0101;
Console.WriteLine(color.GetType());
Console.WriteLine(flags);&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;True
System.UInt32
165&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-003-digit-separators.B-OvhoTt_105dTh.jpg&quot; alt=&quot;Code card showing that underscores make a billion easier to read without changing its value; hex and binary examples are included. Output: True, System.UInt32, 165.&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Filter exceptions with when — Tip #002</title><link>https://khalidabuhakmeh.com/tips/exception-filters/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/exception-filters/</guid><description>A when filter decides whether a catch block handles the exception. If false, the exception keeps propagating.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A when filter decides whether a catch block handles the exception. If false, the exception keeps propagating.&lt;/p&gt;&lt;p&gt;A when filter decides whether a catch block handles the exception. If false, the exception keeps propagating. Everything else propagates with its stack trace intact. On .NET 8+, filter on `ex.HttpRequestError`. It is available since C# 6. The key line is `when (ex.StatusCode == HttpStatusCode.NotFound)` in `filters.cs`. Run it and the output reads `Oh no, not found!`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;using System.Net;
try
{
    using var response = new HttpResponseMessage(
        HttpStatusCode.NotFound);
    response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex)
    when (ex.StatusCode == HttpStatusCode.NotFound)
{
    Console.WriteLine(&quot;Oh no, not found!&quot;);
}&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Oh no, not found!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-002-exception-filters.D-_hR4XK_2qkKXS.jpg&quot; alt=&quot;Code card showing a catch when filter that handles an HTTP 404. Output: Oh no, not found!&quot; /&gt;&lt;/p&gt;</content:encoded></item><item><title>Flatten a collection of collections — Tip #001</title><link>https://khalidabuhakmeh.com/tips/flatten-selectmany/</link><guid isPermaLink="true">https://khalidabuhakmeh.com/tips/flatten-selectmany/</guid><description>SelectMany flattens nested sequences into one. Spread puts the result into a list.</description><pubDate>Tue, 03 Nov 2026 05:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SelectMany flattens nested sequences into one. Spread puts the result into a list.&lt;/p&gt;&lt;p&gt;SelectMany flattens nested sequences into one. Spread puts the result into a list. It is available since C# 12. The key line is `List&amp;lt;int&amp;gt; modern = [.. numbers.SelectMany(n =&amp;gt; n)]` in `flatten.cs`. Run it and the output reads `1, 2, 3, 4, 5, 6, 7, 8, 9`.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;int[][] numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

// classic LINQ
var values = numbers.SelectMany(n =&amp;gt; n).ToList();

// C# 12: collection expression + spread
List&amp;lt;int&amp;gt; modern = [.. numbers.SelectMany(n =&amp;gt; n)];

Console.WriteLine(string.Join(&quot;, &quot;, modern));&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;1, 2, 3, 4, 5, 6, 7, 8, 9&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://khalidabuhakmeh.com/_astro/tip-001-flatten-selectmany.b736naI9_ZsoM96.jpg&quot; alt=&quot;Code card showing SelectMany flattening three arrays; a C# 12 spread places the values in a list. Output: 1 through 9.&quot; /&gt;&lt;/p&gt;</content:encoded></item></channel></rss>