<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Dev Leader - Software Engineering Simplified]]></title><description><![CDATA[Simplifying software engineering concepts and helping you level up as a C# and dotnet developer!]]></description><link>https://hashnode.devleader.ca</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1675635772738/RG9U1UFkE.png</url><title>Dev Leader - Software Engineering Simplified</title><link>https://hashnode.devleader.ca</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 12:42:47 GMT</lastBuildDate><atom:link href="https://hashnode.devleader.ca/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Hello, from BrandGhost!]]></title><description><![CDATA[Hello, from BrandGhost!]]></description><link>https://hashnode.devleader.ca/hello-from-brandghost</link><guid isPermaLink="true">https://hashnode.devleader.ca/hello-from-brandghost</guid><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Sat, 03 Jan 2026 07:58:07 GMT</pubDate><enclosure url="https://brandghostmedia.blob.core.windows.net/user-media/auth0%7C6655f2bd7a159be98aa9d97d/84c8e8f8-43b5-4f67-98a3-da6d995e4e48?sv=2025-11-05&amp;st=2026-01-01T07%3A58%3A06Z&amp;se=2026-01-05T07%3A58%3A06Z&amp;sr=b&amp;sp=r&amp;sig=4JEaUhuLCpiKVs9w4eqRL0g1TOOmS8v5ovPoKPiA1C4%3D" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, from BrandGhost!</p>
<p><img src="https://brandghostmedia.blob.core.windows.net/user-media/auth0%7C6655f2bd7a159be98aa9d97d/84c8e8f8-43b5-4f67-98a3-da6d995e4e48?sv=2025-11-05&amp;st=2026-01-01T07%3A58%3A06Z&amp;se=2026-01-05T07%3A58%3A06Z&amp;sr=b&amp;sp=r&amp;sig=4JEaUhuLCpiKVs9w4eqRL0g1TOOmS8v5ovPoKPiA1C4%3D" alt="image" /></p>
]]></content:encoded></item><item><title><![CDATA[How To Use IServiceCollection in Console Applications – What You Need To Know]]></title><description><![CDATA[When it comes to dependency injection and using the built-in IServiceCollection, the framing feels such that we’re restricted to ASP.NET Core. So if we wanted to use IServiceCollection in console applications instead, what options do we have?
It turn...]]></description><link>https://hashnode.devleader.ca/how-to-use-iservicecollection-in-console-applications-what-you-need-to-know</link><guid isPermaLink="true">https://hashnode.devleader.ca/how-to-use-iservicecollection-in-console-applications-what-you-need-to-know</guid><category><![CDATA[asp.net core]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 20 May 2024 12:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1715688514829/4a30ea0f-7a55-473f-a936-330406ad8ddf.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it comes to dependency injection and using the built-in IServiceCollection, the framing feels such that we’re restricted to <a target="_blank" href="http://ASP.NET">ASP.NET</a> Core. So if we wanted to use <code>IServiceCollection</code> in console applications instead, what options do we have?</p>
<p>It turns out that we absolutely can! In this article, I’ll touch on one of the Microsoft Learn articles as well as explain an alternative approach… That you can run right in your browser with dotnetfiddle!</p>
<hr />
<h2 id="heading-microsoft-learn-article-on-iservicecollection-in-console-applications"><strong>Microsoft Learn Article on IServiceCollection in Console Applications</strong></h2>
<p>Microsoft Learn is a tremendous source of valuable information. I feel like in recent years it continues to surprise me how much valuable information we can find there since I’m used to just relying on MSDN for doc comments and maybe the odd helpful example.</p>
<p>However, in this case, I was a little taken back because the article seemed to be a little bit more cumbersome than I was expecting. If our goal is just to be able to use the <code>IServiceCollection</code> interface so that we can work with our familiar dependency injection API, I would hope that we can stick to the basics.</p>
<p>However, it looks like <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-usage#register-services-for-di">the example in the tutorial</a> goes a little bit beyond that and demonstrates the usage of an <code>HostApplicationBuilder</code>.</p>
<h3 id="heading-hostapplicationbuilder-for-dependency-injection"><strong>HostApplicationBuilder For Dependency Injection</strong></h3>
<p>Let’s look at the example code, which is <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-usage">taken directly from the Microsoft Learn article</a>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.Extensions.DependencyInjection;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Hosting;
<span class="hljs-keyword">using</span> ConsoleDI.Example;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Services.AddTransient&lt;IExampleTransientService, ExampleTransientService&gt;();
builder.Services.AddScoped&lt;IExampleScopedService, ExampleScopedService&gt;();
builder.Services.AddSingleton&lt;IExampleSingletonService, ExampleSingletonService&gt;();
builder.Services.AddTransient&lt;ServiceLifetimeReporter&gt;();

<span class="hljs-keyword">using</span> IHost host = builder.Build();

ExemplifyServiceLifetime(host.Services, <span class="hljs-string">"Lifetime 1"</span>);
ExemplifyServiceLifetime(host.Services, <span class="hljs-string">"Lifetime 2"</span>);

<span class="hljs-keyword">await</span> host.RunAsync();

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ExemplifyServiceLifetime</span>(<span class="hljs-params">IServiceProvider hostProvider, <span class="hljs-keyword">string</span> lifetime</span>)</span>
{
    <span class="hljs-keyword">using</span> IServiceScope serviceScope = hostProvider.CreateScope();
    IServiceProvider provider = serviceScope.ServiceProvider;
    ServiceLifetimeReporter logger = provider.GetRequiredService&lt;ServiceLifetimeReporter&gt;();
    logger.ReportServiceLifetimeDetails(
        <span class="hljs-string">$"<span class="hljs-subst">{lifetime}</span>: Call 1 to provider.GetRequiredService&lt;ServiceLifetimeReporter&gt;()"</span>);

    Console.WriteLine(<span class="hljs-string">"..."</span>);

    logger = provider.GetRequiredService&lt;ServiceLifetimeReporter&gt;();
    logger.ReportServiceLifetimeDetails(
        <span class="hljs-string">$"<span class="hljs-subst">{lifetime}</span>: Call 2 to provider.GetRequiredService&lt;ServiceLifetimeReporter&gt;()"</span>);

    Console.WriteLine();
}
</code></pre>
<p>There’s a lot going on here, of course, because they want to use a single example to demonstrate a few different things. However, my biggest challenges with this is that we can see the <code>IServiceCollection</code> being used via the <code>builder.Services</code> property call… but why do we need to go make an entire hosted application here?</p>
<p>Now, I’m not claiming that you shouldn’t use a hosted application or anything like that — but I am saying that this feels a little bit heavy-handed. If I just want to use <code>IServiceCollection</code> then why am I required to build a hosted application?</p>
<hr />
<h2 id="heading-using-iservicecollection-in-console-applications-directly"><strong>Using IServiceCollection in Console Applications Directly</strong></h2>
<p>It turns out that it’s not complex rocket surgery to get this to work without the hosted application pieces from the Microsoft Learn example. That’s important for me because I want to provide people alternatives when I create content about Autofac and they just want to use IServiceCollection like they are familiar with.</p>
<p>Let’s look at this <a target="_blank" href="https://dotnetfiddle.net/J0U1mm">example code which you can see directly on dotnetfiddle</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/Widget/J0U1mm" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<p>Simply, we can create a new service collection by creating a new <code>ServiceCollection</code> instance:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> services = <span class="hljs-keyword">new</span> ServiceCollection();
</code></pre>
<p>Interestingly there was no dependency on having a hosted application or any other type of builder to do this. We can leverage it directly. It’s also important to note in the dotnetfiddle example that I shared that there are no Nugets imported. So we are able to create this instance without additional packages added.</p>
<p>From there, we can start to register our dependencies directly onto the <code>IServiceCollection</code> (keeping in mind I am only illustrating one type of dependency here):</p>
<pre><code class="lang-csharp">services.AddSingleton&lt;MyService&gt;();
services.AddSingleton&lt;MyDependency&gt;();
</code></pre>
<p>However, this is just the service collection and we still need to create the instance of a service provider that we can resolve dependencies from:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> serviceProvider = services.BuildServiceProvider();
</code></pre>
<p>With the service provider available, we can go ahead and resolve dependencies directly from it:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> myService = serviceProvider.GetRequiredService&lt;MyService&gt;();
</code></pre>
<hr />
<h2 id="heading-wrapping-up-iservicecollection-in-console-applications"><strong>Wrapping Up IServiceCollection in Console Applications</strong></h2>
<p>To wrap up this article, we don’t need to go with a hosted application if we want to leverage an <code>IServiceCollection</code> in console applications for dependency injection. While the Microsoft Learn article is awesome with plenty of solid examples, I felt like it overcomplicated what could otherwise be a bit more straightforward.</p>
<p>So if you’re looking to go leverage an <code>IServiceCollection</code> in your console projects instead of Autofac, go nuts! Even though I like using Autofac for all of my dependency injection, I think it’s important to understand the options that you have!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Autofac ComponentRegistryBuilder in ASP.NET Core – How To Register Dependencies (Part 3)]]></title><description><![CDATA[In this article, we’ll be exploring how to use Autofac ComponentRegistryBuilder in ASP.NET Core. Prior articles in this series have highlighted some challenges for getting set up to do C# plugin architectures — at least for my own standards. I’ll be ...]]></description><link>https://hashnode.devleader.ca/autofac-componentregistrybuilder-in-aspnet-core-how-to-register-dependencies-part-3</link><guid isPermaLink="true">https://hashnode.devleader.ca/autofac-componentregistrybuilder-in-aspnet-core-how-to-register-dependencies-part-3</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[C#]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Thu, 09 May 2024 12:00:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1714757312455/486c15dc-8d0e-48a3-9e1a-743c96aea43a.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we’ll be exploring how to use Autofac ComponentRegistryBuilder in ASP.NET Core. Prior articles in this series have highlighted some challenges for getting set up to do C# plugin architectures — at least for my own standards. I’ll be walking us through how this approach can help overcome some of the challenges that have previously been highlighted.</p>
<p>This will be part of a series where I explore dependency resolution with Autofac inside of ASP.NET Core. I'll be sure to include the series below as the issues are published:</p>
<ul>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/04/30/autofacserviceproviderfactory-in-asp-net-core-problems-with-dependency-injection-part-1/">Part 1: AutofacServiceProviderFactory in ASP.NET Core - Problems With Dependency Injection</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/05/02/autofac-containerbuilder-in-asp-net-core-what-you-need-to-know-part-2">Part 2: Autofac ContainerBuilder In ASP.NET Core – What You Need To Know</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/wp-content/uploads/2024/05/Autofac-ComponentRegistryBuilder-in-ASPNET-Core-How-To-Register-Dependencies.webp">Part 3: Autofac ComponentRegistryBuilder in ASP.NET Core - How To Register Dependencies</a></p>
</li>
</ul>
<p>At the end of this series, you'll be able to more confidently explore plugin architectures inside of ASP.NET Core and Blazor -- which will be even more content for you to explore. Keep your eyes peeled on <a target="_blank" href="https://dometrain.com/author/nick-cosentino?affcode=1115529_nl-teyzg">my Dometrain courses for a more guided approach to these topics later in 2023</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-where-did-we-leave-off-with-autofac-in-aspnet-core"><strong>Where Did We Leave Off With Autofac in ASP.NET Core?</strong></h2>
<p>The previous two articles looked at the following scenarios:</p>
<ul>
<li><p>Setting up using the <code>AutofacServiceProviderFactory</code> as the standard recommended approach</p>
</li>
<li><p>Skipping <code>AutofacServiceProviderFactory</code> and using Autofac <code>ContainerBuilder</code> directly</p>
</li>
</ul>
<p>In both cases, we were able to get a web application up and running using Autofac for dependency injection. However, both of these had limitations around:</p>
<ul>
<li><p>Accessing the <code>WebApplication</code> instance on the container</p>
</li>
<li><p>Weird nuances with minimal API support</p>
</li>
</ul>
<p>While both options are absolutely viable — and may be great for you given your constraints — I wanted to push a bit further to see if the wrinkles could be ironed out. I want to strive towards having configuration done in <a target="_blank" href="https://www.devleader.ca/2023/10/02/how-to-organize-autofac-modules-5-tips-for-organizing-code/">separate Autofac modules</a> and pushing towards a C# plugin architecture for the majority of my application development.</p>
<hr />
<h2 id="heading-exploring-a-sample-aspnet-core-application"><strong>Exploring A Sample ASP.NET Core Application</strong></h2>
<p>This one is going to be different than the previous articles — we’ve achieved plugin status. I want to show you how the code from the previous examples can now be broken out into more dedicated pieces. Most of what we’ve gone over before is the same concept, but I’ve reduced the weather route to something more contrived just to eliminate the waste.</p>
<p>Make sure to follow along with <a target="_blank" href="https://youtu.be/JYD0VKKXle8">this video on Autofac</a> for additional explanations as we go through:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/JYD0VKKXle8">https://youtu.be/JYD0VKKXle8</a></div>
<p> </p>
<h3 id="heading-the-entry-point-configuration"><strong>The Entry Point Configuration</strong></h3>
<p>Here’s how simple our Program.cs file is now:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> FullResolveWebApi().RunAsync(CancellationToken.None);
</code></pre>
<p>That’s right — one line of code. But okay, you’re probably curious where all the setup actually takes place. Let’s go a bit deeper:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">FullResolveWebApi</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">RunAsync</span>(<span class="hljs-params">CancellationToken cancellationToken</span>)</span>
    {
        <span class="hljs-keyword">var</span> containerBuilder = <span class="hljs-keyword">new</span> MyContainerBuilder();
        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> container = containerBuilder.Build();
        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> scope = container.BeginLifetimeScope();

        <span class="hljs-keyword">var</span> app = scope
            .Resolve&lt;ConfiguredWebApplication&gt;()
            .WebApplication;
        <span class="hljs-keyword">await</span> app.RunAsync(cancellationToken).ConfigureAwait(<span class="hljs-literal">false</span>);
    }
}
</code></pre>
<p>This looks familiar to what we saw in the previous example! We’re able to get the goodness of that really lean startup configuration But wait! What’s that custom <code>MyContainerBuilder</code> class?!</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;

<span class="hljs-keyword">using</span> System.Reflection;

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyContainerBuilder</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> IContainer <span class="hljs-title">Build</span>(<span class="hljs-params"></span>)</span>
    {
        ContainerBuilder containerBuilder = <span class="hljs-keyword">new</span>();

        <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> do some assembly scanning if needed</span>
        <span class="hljs-keyword">var</span> assembly = Assembly.GetExecutingAssembly();
        containerBuilder.RegisterAssemblyModules(assembly);

        <span class="hljs-keyword">var</span> container = containerBuilder.Build();
        <span class="hljs-keyword">return</span> container;
    }
}
</code></pre>
<p>This is missing from the code above if we compare it to the previous article, but it can also be extended to do assembly scanning if that’s a requirement. So far, so good. We have one more piece though, and that’s <code>ConfiguredWebApplication</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">ConfiguredWebApplication</span>(<span class="hljs-params">
    WebApplication _webApplication,
    IReadOnlyList&lt;PreApplicationConfiguredMarker&gt; _markers</span>)</span>
{
    <span class="hljs-keyword">public</span> WebApplication WebApplication =&gt; _webApplication;
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> record <span class="hljs-title">PreApplicationBuildMarker</span>(<span class="hljs-params"></span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> record <span class="hljs-title">PreApplicationConfiguredMarker</span>(<span class="hljs-params"></span>)</span>;
</code></pre>
<p>This marker record might seem a bit confusing but we’ll tie this all together in a dedicated section.</p>
<h3 id="heading-webapplicationbuilder-autofac-module"><strong>WebApplicationBuilder Autofac Module</strong></h3>
<p>Now that we’ve seen how our initial ASP NET Core application bootstrap code is looking, it’s time to look at some of the core dependency registration that’s going to be a union of what we saw in the previous articles AND some new behavior:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;
<span class="hljs-keyword">using</span> Autofac.Extensions.DependencyInjection;

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WebApplicationBuilderModule</span> : <span class="hljs-title">global</span>::<span class="hljs-title">Autofac.Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder builder</span>)</span>
    {
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(Environment.GetCommandLineArgs());
                <span class="hljs-keyword">return</span> builder;
            })
            .SingleInstance();
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> config = ctx.Resolve&lt;WebApplicationBuilder&gt;().Configuration;
                <span class="hljs-keyword">return</span> config;
            })
            .As&lt;IConfiguration&gt;()
            .SingleInstance();

        WebApplication? cachedWebApplication = <span class="hljs-literal">null</span>;
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">if</span> (cachedWebApplication <span class="hljs-keyword">is</span> not <span class="hljs-literal">null</span>)
                {
                    <span class="hljs-keyword">return</span> cachedWebApplication;
                }

                <span class="hljs-keyword">var</span> webApplicationBuilder = ctx.Resolve&lt;WebApplicationBuilder&gt;();
                ctx.Resolve&lt;IReadOnlyList&lt;PreApplicationBuildMarker&gt;&gt;();

                webApplicationBuilder.Host.UseServiceProviderFactory(<span class="hljs-keyword">new</span> AutofacServiceProviderFactory(containerBuilder =&gt;
                {
                    <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> registration <span class="hljs-keyword">in</span> ctx.ComponentRegistry.Registrations)
                    {
                        containerBuilder.ComponentRegistryBuilder.Register(registration);
                    }

                    containerBuilder
                        .RegisterInstance(webApplicationBuilder)
                        .SingleInstance();
                }));

                cachedWebApplication = webApplicationBuilder.Build();
                <span class="hljs-keyword">return</span> cachedWebApplication;
            })
            .SingleInstance();
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> app = ctx.Resolve&lt;WebApplication&gt;();
                app.UseHttpsRedirection();
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PreApplicationConfiguredMarker();
            })
            .SingleInstance();
        builder
            .RegisterType&lt;ConfiguredWebApplication&gt;()
            .SingleInstance();
    }
}
</code></pre>
<p>You’ll notice that the code snippet above shows that we’re now mixing in the <code>AutofacServiceProviderFactory</code> alongside our standalone Autofac <code>ContainerBuilder</code> approach. What we’re able to do is leverage this code to re-register some of the dependency registrations on the second Autofac <code>ContainerBuilder</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> registration <span class="hljs-keyword">in</span> ctx.ComponentRegistry.Registrations)
{
    containerBuilder.ComponentRegistryBuilder.Register(registration);
}
</code></pre>
<p>Now that we can duplicate our registrations, we get the registration of the <code>WebApplication</code> from the parent container onto the dedicated <code>WebApplication</code>‘s <code>ContainerBuilder</code>. But two things we should note:</p>
<ul>
<li><p>We need to cache the <code>WebApplication</code> instance. This is because later on when the <code>WebApplication</code> instance itself needs to resolve dependencies that depend on an instance of <code>WebApplication</code>, it will go re-run the registration <em>even though it’s a single instance</em>! This is because this is a duplicated registration across the container that has never technically been executed at the time of registration. We may need to pay special attention to this sort of thing as we go forward to avoid expensive re-resolution of types.</p>
</li>
<li><p>We see another marker type: <code>PreApplicationConfiguredMarker</code>. What’s with these markers?!</p>
</li>
</ul>
<h3 id="heading-marker-classes-for-controlling-dependency-ordering-and-requirements"><strong>Marker Classes for Controlling Dependency Ordering and Requirements</strong></h3>
<p>So far we’ve seen two instances of marker types. These marker types are a way that we can force certain registration code to execute before some other registration code executes. This is a more flexible way of saying “I don’t care which types specifically get registered or which registration code runs, but anyone that needs to be registered before some checkpoint, make sure you return one of these”. This allows us to force code to execute before a checkpoint.</p>
<p>If we consider the code in the example above, we see that the <code>ConfiguredWebApplication</code> instance requires the full collection of <code>PreApplicationConfiguredMarker</code> instances. This means that we can’t even create an instance of <code>ConfiguredWebApplication</code> until all dependent code, as indicated by our marker type, has finished executing. This essentially forces Autofac to run certain code for us because it will attempt to run all code that provides one of these marker instances.</p>
<p>The two markers we see in this example code are very naive/primitive — however, this concept can be expanded to provide more robust checkpoints in your dependency registration process.</p>
<hr />
<h2 id="heading-c-plugin-architecture-in-aspnet-core-unlocked"><strong>C# Plugin Architecture in ASP.NET Core Unlocked!</strong></h2>
<p>The cat’s out of the bag! We can now successfully create an Autofac module for a plugin! This code shows us enabling C# plugin architecture in ASP.NET Core as we’re able to add a new discoverable module that adds its own API endpoints:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Plugins</span>;

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PluginModule</span> : <span class="hljs-title">Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder builder</span>)</span>
    {
        <span class="hljs-comment">// load whatever dependencies you want in your plugin</span>
        <span class="hljs-comment">// taking note that they will be able to have access</span>
        <span class="hljs-comment">// to services/dependencies in the main application</span>
        <span class="hljs-comment">// by default</span>
        builder.RegisterType&lt;DependencyA&gt;().SingleInstance();
        builder.RegisterType&lt;DependencyB&gt;().SingleInstance();
        builder.RegisterType&lt;DependencyC&gt;().SingleInstance();

        <span class="hljs-comment">// minimal APIs can resolve dependencies from the</span>
        <span class="hljs-comment">// method signature itself</span>
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> app = ctx.Resolve&lt;WebApplication&gt;();

                app.MapGet(
                    <span class="hljs-string">"/hello"</span>,
                    (
                        DependencyA dependencyA
                      , DependencyB dependencyB
                      , DependencyC dependencyC
                    ) =&gt;
                    {
                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span>
                        {
                            AAA = dependencyA.ToString(),
                            BBB = dependencyB.ToString(),
                            CCC = dependencyC.ToString(),
                        };
                    });

                <span class="hljs-comment">// this is a marker to signal a dependency</span>
                <span class="hljs-comment">// before the application can be considered</span>
                <span class="hljs-comment">// configured</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PreApplicationConfiguredMarker();
            })
            .SingleInstance();
    }
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyA</span>(<span class="hljs-params">
    WebApplicationBuilder _webApplicationBuilder</span>)</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">string</span> <span class="hljs-title">ToString</span>(<span class="hljs-params"></span>)</span> =&gt; _webApplicationBuilder.ToString();
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyB</span>(<span class="hljs-params">
    Lazy&lt;WebApplication&gt; _webApplication</span>)</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">string</span> <span class="hljs-title">ToString</span>(<span class="hljs-params"></span>)</span> =&gt; _webApplication.Value.ToString();
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyC</span>(<span class="hljs-params">
    IConfiguration _configuration</span>)</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">string</span> <span class="hljs-title">ToString</span>(<span class="hljs-params"></span>)</span> =&gt; _configuration.ToString();
}
</code></pre>
<p>If you’d like a more full explanation as to what you’re seeing, I highly recommend you read the articles linked at the top of this one first just to get an idea of why we have some dependencies set up like this. The TL;DR is that this code demonstrates that we can access some dependencies that are of interest to us when building plugin architectures.</p>
<h3 id="heading-what-benefits-for-c-plugin-architecture-have-been-unlocked"><strong>What Benefits For C# Plugin Architecture Have Been Unlocked?</strong></h3>
<p>The code examples in this article are essentially marrying approaches from two of the previous articles… so hopefully we have the best of both worlds! Let’s have a look:</p>
<ul>
<li><p>Can access <code>WebApplicationBuilder</code> instance from the <code>WebApplication</code>‘s dependency container.</p>
</li>
<li><p>Can access <code>IConfiguration</code> instance from the <code>WebApplication</code>‘s dependency container.</p>
</li>
<li><p>Can access <code>WebApplication</code> instance from the <code>WebApplication</code>‘s dependency container.</p>
</li>
<li><p>Can resolve Autofac ContainerBuilder dependencies on the minimal APIs directly</p>
</li>
<li><p>Can create separate Autofac modules (i.e. for plugin usage) that register minimal APIs directly onto the <code>WebApplication</code> instance</p>
</li>
<li><p>Can get an extremely lightweight (one line!) entry point to our application. The core “skeleton” application code is fundamentally just setting up dependencies to be resolved.</p>
</li>
</ul>
<p>All of these are boxes that I wanted to check before continuing to build plugins. With this infrastructure in place, I feel much more confident!</p>
<h3 id="heading-what-gaps-are-left-for-c-plugin-architecture"><strong>What Gaps Are Left For C# Plugin Architecture?</strong></h3>
<p>Of course, we need to look at both pros AND cons when we analyze things. Let’s dive in:</p>
<ul>
<li><p>We have two dependency containers to worry about. In theory, the usage of Autofac ComponentRegistryBuilder in ASP.NET Core should allow us to clone registrations between the two, but more complexity can potentially arise from this as we continue.</p>
</li>
<li><p>We saw an interesting need to cache the <code>WebApplication</code> instance to avoid dependency recreation — are there other scenarios like this we haven’t hit yet?</p>
</li>
<li><p>One of the general plugin architecture concerns: Being able to configure EVERYTHING with plugins can make some things harder to find and structure. Do we really need these little marker types to help organize ourselves?</p>
</li>
</ul>
<hr />
<h2 id="heading-wrapping-up-autofac-componentregistrybuilder-in-aspnet-core"><strong>Wrapping Up Autofac ComponentRegistryBuilder in ASP.NET Core</strong></h2>
<p>Overall, I’m quite happy with how using Autofac ComponentRegistryBuilder in ASP.NET Core has allowed us to progress our dependency injection patterns. This approach which I’ve highlighted in the article has made it significantly easier for me to go structure plugins the way that I’d like to in a C# plugin architecture. Not without tradeoffs — but I feel this pattern fits my needs.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Autofac ContainerBuilder in ASP.NET Core – What You Need To Know (Part 2)]]></title><description><![CDATA[There are many ways to manage dependency injection inside our applications, and I think it’s important to understand the benefits and limitations of different approaches. Using an Autofac ContainerBuilder in ASP.NET Core as the primary way to structu...]]></description><link>https://hashnode.devleader.ca/autofac-containerbuilder-in-aspnet-core-what-you-need-to-know-part-2</link><guid isPermaLink="true">https://hashnode.devleader.ca/autofac-containerbuilder-in-aspnet-core-what-you-need-to-know-part-2</guid><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[coding]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Wed, 08 May 2024 12:00:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1714651712774/2d5b51e7-292a-4934-90c1-a44eece99de0.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are many ways to manage dependency injection inside our applications, and I think it’s important to understand the benefits and limitations of different approaches. Using an Autofac <code>ContainerBuilder</code> in ASP.NET Core as the primary way to structure your dependencies instead of using the suggested <code>AutofacServiceProviderFactory</code> is one such path we can explore!</p>
<p>In this article, I highlight how to use Autofac’s ContainerBuilder in your ASP.NET Core application instead of the AutofacServiceProviderFactory. We’ll look at what you can and cannot do with this approach, versus the other approaches we have access to with dependency injection.</p>
<p>This will be part of a series where I explore dependency resolution with Autofac inside of ASP.NET Core. I'll be sure to include the series below as the issues are published:</p>
<ul>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/04/30/autofacserviceproviderfactory-in-asp-net-core-problems-with-dependency-injection-part-1/">Part 1: AutofacServiceProviderFactory in ASP.NET Core - Problems With Dependency Injection</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/05/02/autofac-containerbuilder-in-asp-net-core-what-you-need-to-know-part-2">Part 2: Autofac ContainerBuilder In ASP.NET Core – What You Need To Know</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/wp-content/uploads/2024/05/Autofac-ComponentRegistryBuilder-in-ASPNET-Core-How-To-Register-Dependencies.webp">Part 3: Autofac ComponentRegistryBuilder in ASP.NET Core - How To Register Dependencies</a></p>
</li>
</ul>
<p>At the end of this series, you'll be able to more confidently explore plugin architectures inside of ASP.NET Core and Blazor -- which will be even more content for you to explore. Keep your eyes peeled on <a target="_blank" href="https://dometrain.com/author/nick-cosentino?affcode=1115529_nl-teyzg">my Dometrain courses for a more guided approach to these topics later in 2023</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-the-problem-with-autofacserviceproviderfactory"><strong>The Problem With AutofacServiceProviderFactory</strong></h2>
<p>To be fair, the section title is <em>almost</em> click-bait. I do think that <code>AutofacServiceProviderFactory</code> being used as <a target="_blank" href="https://www.devleader.ca/2024/03/19/autofac-in-asp-net-core-how-to-avoid-this-debugging-nightmare/">the suggested way to set up Autofac in your ASP.NET Core applications</a> is great for most applications. The great majority of developers who want to use Autofac as their dependency injection framework of choice would not run into many issues at all this way.</p>
<p>It does afford us the ability to:</p>
<ul>
<li><p>Access the <code>WebApplicationBuilder</code> (and anything available at this point in time)</p>
</li>
<li><p>Access to the instance of <code>IConfiguration</code> (also available off the <code>WebApplicationBuilder</code> instance)</p>
</li>
<li><p>Ability to pass dependencies onto minimal APIs</p>
</li>
</ul>
<p>But the big issue for me: We can’t access the <code>WebApplication</code> instance. When I build plugin architectures in C#, in particular building ASP.NET Core applications, I like to have access to the <code>WebApplication</code> instance in order to register routes. This allows me to register minimal APIs from my plugins with ease, which technically only need access to an implementation of <code>IEndpointRouteBuilder</code> to get the handy syntax.</p>
<p>Can I register non-minimal APIs without this? Absolutely. Is there another way to provide similar syntax and not require a <code>WebApplication</code> instance? Very likely. But instead of trying to work around THAT problem, I wanted to see if I could just get access to the dependency I am interested in.</p>
<p>It was time to change the plan on how to set up my dependency container!</p>
<hr />
<h2 id="heading-exploring-a-sample-aspnet-core-application"><strong>Exploring A Sample ASP.NET Core Application</strong></h2>
<p>Let’s look at a sample application so that we have some common ground to explore. If you’ve <a target="_blank" href="https://www.devleader.ca/2024/04/30/autofacserviceproviderfactory-in-asp-net-core-problems-with-dependency-injection-part-1/">read the previous article</a>, this will look similar — a variation of the sample weather application:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;

<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-comment">// personal opinion:</span>
<span class="hljs-comment">// I absolutely love having the entry point of my</span>
<span class="hljs-comment">// applications being essentially:</span>
<span class="hljs-comment">// - make my dependencies</span>
<span class="hljs-comment">// - give me the primary dependency</span>
<span class="hljs-comment">// - use it</span>
<span class="hljs-comment">// - ... nothing else :)</span>
ContainerBuilder containerBuilder = <span class="hljs-keyword">new</span>();
containerBuilder.RegisterModule&lt;MyModule&gt;();

<span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> container = containerBuilder.Build();
<span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> scope = container.BeginLifetimeScope();
<span class="hljs-keyword">var</span> app = scope.Resolve&lt;WebApplication&gt;();
app.Run();

<span class="hljs-function"><span class="hljs-keyword">internal</span> record <span class="hljs-title">WeatherForecast</span>(<span class="hljs-params">DateOnly Date, <span class="hljs-keyword">int</span> TemperatureC, <span class="hljs-keyword">string</span>? Summary</span>)</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> TemperatureF =&gt; <span class="hljs-number">32</span> + (<span class="hljs-keyword">int</span>)(TemperatureC / <span class="hljs-number">0.5556</span>);
}

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyModule</span> : <span class="hljs-title">Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder containerBuilder</span>)</span>
    {
        containerBuilder.RegisterType&lt;DependencyA&gt;().SingleInstance();
        containerBuilder.RegisterType&lt;DependencyB&gt;().SingleInstance();
        containerBuilder.RegisterType&lt;DependencyC&gt;().SingleInstance();
        containerBuilder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(Environment.GetCommandLineArgs());
                <span class="hljs-keyword">return</span> builder;
            })
            .SingleInstance();
        containerBuilder
            .Register(ctx =&gt; ctx.Resolve&lt;WebApplicationBuilder&gt;().Configuration)
            .As&lt;IConfiguration&gt;()
            .SingleInstance();
        containerBuilder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> builder = ctx.Resolve&lt;WebApplicationBuilder&gt;();

                <span class="hljs-keyword">var</span> app = builder.Build();
                app.UseHttpsRedirection();

                <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> the problem is that the Autofac ContainerBuilder</span>
                <span class="hljs-comment">// was used to put all of these pieces together,</span>
                <span class="hljs-comment">// but we never told the web stack to use Autofac as the</span>
                <span class="hljs-comment">// service provider.</span>
                <span class="hljs-comment">// this means that the minimal API will never be able to</span>
                <span class="hljs-comment">// find services off the container. we would need to resolve</span>
                <span class="hljs-comment">// them BEFORE the API is called, like in this registration</span>
                <span class="hljs-comment">// method itself, from the context that is passed in.</span>
                <span class="hljs-comment">//DependencyA dependencyA = ctx.Resolve&lt;DependencyA&gt;();</span>

                <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> But... What happens if something wants to take a</span>
                <span class="hljs-comment">// dependency on the WebApplication instance itself? Once the</span>
                <span class="hljs-comment">// web application has been built, there's no more adding</span>
                <span class="hljs-comment">// dependencies to it!</span>

                <span class="hljs-keyword">var</span> summaries = <span class="hljs-keyword">new</span>[]
                {
                    <span class="hljs-string">"Freezing"</span>, <span class="hljs-string">"Bracing"</span>, <span class="hljs-string">"Chilly"</span>, <span class="hljs-string">"Cool"</span>, <span class="hljs-string">"Mild"</span>, <span class="hljs-string">"Warm"</span>, <span class="hljs-string">"Balmy"</span>, <span class="hljs-string">"Hot"</span>, <span class="hljs-string">"Sweltering"</span>, <span class="hljs-string">"Scorching"</span>
                };

                app.MapGet(
                    <span class="hljs-string">"/weatherforecast"</span>,
                    (
                        [<span class="hljs-meta">FromServices</span>] DependencyA dependencyA
                      , [FromServices] DependencyB dependencyB
                      , [FromServices] DependencyC dependencyC
                    ) =&gt;
                    {
                        <span class="hljs-keyword">var</span> forecast = Enumerable
                            .Range(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>)
                            .Select(index =&gt; <span class="hljs-keyword">new</span> WeatherForecast
                            (
                                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                                Random.Shared.Next(<span class="hljs-number">-20</span>, <span class="hljs-number">55</span>),
                                summaries[Random.Shared.Next(summaries.Length)]
                            ))
                            .ToArray();
                        <span class="hljs-keyword">return</span> forecast;
                    });

                <span class="hljs-keyword">return</span> app;
            })
            .SingleInstance();
    }
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyA</span>(<span class="hljs-params">
    WebApplicationBuilder _webApplicationBuilder</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyB</span>(<span class="hljs-params">
    WebApplication _webApplication</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyC</span>(<span class="hljs-params">
    IConfiguration _configuration</span>)</span>;
</code></pre>
<p>One callout of this approach is that using the Autofac <code>ContainerBuilder</code> class as our primary dependency container affords us the opportunity to structure our entry point to just:</p>
<ul>
<li><p>Container creation</p>
</li>
<li><p>Dependency registration</p>
</li>
<li><p>Primary dependency resolution</p>
</li>
<li><p>… Call a single method to start the app up!</p>
</li>
</ul>
<p>This is, in my opinion, ideal application startup code. Why? Because you never need to come back here to touch it. Ever. No matter how many things you add in! And that’s all because you can scan assemblies to load more modules.</p>
<p>Again, this is a personal preference of mine and I am not trying to claim this should be everyone’s goal.</p>
<h3 id="heading-the-flaws-of-autofac-containerbuilder-in-aspnet-core"><strong>The Flaws of Autofac ContainerBuilder in ASP.NET Core</strong></h3>
<p>Of course, another approach that isn’t quite bulletproof. So let’s discuss what we DON’T get with this setup of Autofac:</p>
<ul>
<li><p>Service-resolved parameters passed on minimal APIs simply don’t work. The <code>WebApplication</code> that was built is not configured to use Autofac as the dependency injection framework!</p>
</li>
<li><p>Like the previous article, we still can’t get the <code>WebApplication</code> instance on the dependency container… So we didn’t make any advancements specifically on accessing that.</p>
</li>
</ul>
<p>But that’s mostly it! It’s not a terrible list of drawbacks, but the Autofac ContainerBuilder approach was not a silver bullet solution for us. So what did we get out of it? <a target="_blank" href="https://youtu.be/FJziGcvuzmo">This video on Autofac</a> will also help explain:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/FJziGcvuzmo">https://youtu.be/FJziGcvuzmo</a></div>
<p> </p>
<h3 id="heading-the-benefits-of-autofac-containerbuilder-in-aspnet-core"><strong>The Benefits of Autofac ContainerBuilder in ASP.NET Core</strong></h3>
<p>Pros and cons for everything we do! Now that we’ve seen the issues with Autofac ContainerBuilder in ASP.NET Core, it’s time to look at what advancements we got out of this:</p>
<ul>
<li><p>We can still access the <code>WebApplicationBuilder</code> and <code>IConfiguration</code> instances, so that’s a comparable benefit to using the <code>AutofacServiceProviderFactory</code> approach.</p>
</li>
<li><p>We can get a very streamlined entry point to our program, which I really like to see. Container creation, registration, resolve your entry point method, and that’s all!</p>
</li>
<li><p>Minimal APIs work, but not with dependencies. Still, we can pre-resolve the dependencies the minimal APIs want and pass those in at the time of method registration. See the commented code!</p>
</li>
</ul>
<hr />
<h2 id="heading-more-inversion-for-plugin-based-aspnet-routes"><strong>More Inversion for Plugin-Based ASP.NET Routes?</strong></h2>
<p>We saw that we could register minimal APIs within an Autofac registration method, but unfortunately, we cannot resolve dependencies from the container directly on the minimal API call itself. We could go build a dedicated class like the following that handles route definitions with dependencies being resolved automatically:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">WeatherForecastRoutes</span>(<span class="hljs-params">
    DependencyA _dependencyA
    // FIXME: still can<span class="hljs-string">'t depend on this because
    // we can'</span>t <span class="hljs-keyword">get</span> the WebApplication
//, DependencyB _dependencyB 
  , DependencyC _dependencyC</span>)</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span>[] _summaries = <span class="hljs-keyword">new</span>[]
    {
        <span class="hljs-string">"Freezing"</span>, <span class="hljs-string">"Bracing"</span>, <span class="hljs-comment">// ...</span>
    };

    <span class="hljs-function"><span class="hljs-keyword">public</span> WeatherForecast[] <span class="hljs-title">Forecast</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">var</span> forecast = Enumerable.Range(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>).Select(index =&gt;
            <span class="hljs-keyword">new</span> WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(<span class="hljs-number">-20</span>, <span class="hljs-number">55</span>),
                _summaries[Random.Shared.Next(_summaries.Length)]
            ))
            .ToArray();
        <span class="hljs-keyword">return</span> forecast;
    }
}
</code></pre>
<p>The automatic resolution happens if we have this class AND the dependencies all on the same container. Then it’s just a matter of calling this code:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> weatherForecastRoutes = ctx.Resolve&lt;WeatherForecastRoutes&gt;();
app.MapGet(<span class="hljs-string">"/weatherforecast2"</span>, weatherForecastRoutes.Forecast);
</code></pre>
<p>This still sucks a bit from a plugin perspective because we’d need to go resolve all of the route classes manually just to call the registration code like that — all stemming from the fact that these things can’t resolve their own access to the <code>WebApplication</code> instance.</p>
<p>But wait… What if we flip things around? What if we could resolve some interface like <code>IRegisterRoutes</code> and pass in the <code>WebApplication</code> instance?!</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> make sure to register WeatherForecastRouteRegistrar on the</span>
<span class="hljs-comment">// autofac container as IRegisterRoutes!</span>

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">IRegisterRoutes</span>
{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">RegisterRoutes</span>(<span class="hljs-params">WebApplication app</span>)</span>;
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">WeatherForecastRouteRegistrar</span>(<span class="hljs-params">
    WeatherForecastRoutes _weatherForecastRoutes</span>) :
    IRegisterRoutes</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">RegisterRoutes</span>(<span class="hljs-params">WebApplication app</span>)</span>
    {
        app.MapGet(<span class="hljs-string">"/weatherforecast2"</span>, _weatherForecastRoutes.Forecast);
    }
}

<span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> add this to the autofac code where the </span>
<span class="hljs-comment">// WebApplication instance is built:</span>
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> registrar <span class="hljs-keyword">in</span> ctx.Resolve&lt;IEnumerable&lt;IRegisterRoutes&gt;&gt;())
{
    registrar.RegisterRoutes(app);
}
</code></pre>
<p>Now we don’t even need to care if the <code>WebApplication</code> instance is accessible to our plugins! Maybe the first version wasn’t so limiting after all? Maybe we’re onto something here… But the next article should explain this in more detail.</p>
<hr />
<h2 id="heading-wrapping-up-autofac-containerbuilder-in-aspnet-core"><strong>Wrapping Up Autofac ContainerBuilder in ASP.NET Core</strong></h2>
<p>In this article, I explored using an Autofac <code>ContainerBuilder</code> explicitly instead of using <code>AutofacServiceProviderFactory</code> as is normally suggested. We saw some similar benefits and drawbacks, but also a different set of things to consider. Each way can offer pros and cons depending on what you’re after in your application.</p>
<p>What was interesting was that if we’re trying to work towards plugins, we might not even need to access the <code>WebApplication</code> instance from our plugins at all! If we care about minimal APIs, this might still be limiting… but otherwise, we’re onto an interesting line of thinking!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca">https://weekly.devleader.ca</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AutofacServiceProviderFactory in ASP.NET Core – Problems With Dependency Injection (Part 1)]]></title><description><![CDATA[We have plenty of awesome options for dependency injection when working in ASP.NET Core applications. For the most part, if you’re not building anything super complicated concerning your types or your software architecture, you can get by with the bu...]]></description><link>https://hashnode.devleader.ca/autofacserviceproviderfactory-in-aspnet-core-problems-with-dependency-injection-part-1</link><guid isPermaLink="true">https://hashnode.devleader.ca/autofacserviceproviderfactory-in-aspnet-core-problems-with-dependency-injection-part-1</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[coding]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[C#]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[asp.net core]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Tue, 07 May 2024 12:00:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1714522115271/2d624956-ff38-4b7c-9151-94fba5b6f56a.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We have plenty of awesome options for dependency injection when working in ASP.NET Core applications. For the most part, if you’re not building anything super complicated concerning your types or your software architecture, you can get by with the built-in IServiceCollection. However, we can use AutofacServiceProviderFactory in ASP.NET Core to make Autofac our dependency container of choice in our app!</p>
<p>In this article, I highlight how to use AutofacServiceProviderFactory in your ASP.NET Core application along with what you can and cannot do with it. Having many options for dependency injection means that we have many pros and cons to analyze!</p>
<p>This will be part of a series where I explore dependency resolution with Autofac inside of ASP.NET Core. I'll be sure to include the series below as the issues are published:</p>
<ul>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/04/30/autofacserviceproviderfactory-in-asp-net-core-problems-with-dependency-injection-part-1/">Part 1: AutofacServiceProviderFactory in ASP.NET Core - Problems With Dependency Injection</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/05/02/autofac-containerbuilder-in-asp-net-core-what-you-need-to-know-part-2">Part 2: Autofac ContainerBuilder In ASP.NET Core – What You Need To Know</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/wp-content/uploads/2024/05/Autofac-ComponentRegistryBuilder-in-ASPNET-Core-How-To-Register-Dependencies.webp">Part 3: Autofac ComponentRegistryBuilder in ASP.NET Core - How To Register Dependencies</a></p>
</li>
</ul>
<p>At the end of this series, you'll be able to more confidently explore plugin architectures inside of ASP.NET Core and Blazor -- which will be even more content for you to explore. Keep your eyes peeled on <a target="_blank" href="https://dometrain.com/author/nick-cosentino?affcode=1115529_nl-teyzg">my Dometrain courses for a more guided approach to these topics later in 2023</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-dependency-injection-a-primer"><strong>Dependency Injection: A Primer</strong></h2>
<h3 id="heading-what-is-dependency-injection"><strong>What is Dependency Injection</strong></h3>
<p>Dependency Injection (DI) is a <a target="_blank" href="https://www.devleader.ca/2023/12/31/the-big-list-of-design-patterns-everything-you-need-to-know/">design pattern</a> used in programming to make software systems easier to develop, test, and maintain. In C#, like in many other programming languages, dependency injection helps to decouple the components of your applications. Ideally, this leads to developing software that is more flexible and extensible.</p>
<p>Dependency Injection is about removing the hard-coded dependencies and making it possible to change them, either at runtime or compile time. This can be useful for many reasons, such as allowing a program to use different databases or testing components by replacing them with mock objects.</p>
<p>Consider a code example where we create an instance of a car with an engine:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Car</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IEngine _engine;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Car</span>(<span class="hljs-params"></span>)</span>
    {
       <span class="hljs-comment">// The Car class directly depends on the GasEngine class.</span>
        _engine = <span class="hljs-keyword">new</span> GasEngine();  
    }
}
</code></pre>
<p>We can instead “inject” the dependency via the constructor:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Car</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IEngine _engine;

    <span class="hljs-comment">// The engine is injected into the car via the constructor</span>
    <span class="hljs-comment">// so now there is no direct dependency on the Engine class,</span>
    <span class="hljs-comment">// but there is a dependency on the IEngine interface</span>
    <span class="hljs-comment">// which has nothing to do with the implementation</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Car</span>(<span class="hljs-params">IEngine engine</span>)</span>
    {
        _engine = engine;
    }
}
</code></pre>
<p>We can even use the idea of a “Dependency Container” that helps make this process seem a bit more magical by not requiring us to explicitly create instances of objects by passing in dependencies. Instead, the container allows us to resolve these dependencies. More on that in the next section!</p>
<h3 id="heading-what-is-autofac"><strong>What is Autofac?</strong></h3>
<p><a target="_blank" href="https://www.devleader.ca/2023/08/22/dependency-injection-how-to-start-with-autofac-the-easy-way/">Autofac is a popular inversion of control (IoC) container for .NET</a>. It manages the dependencies between classes by injecting instances where needed, thereby facilitating a more modular and testable codebase. Autofac is used extensively in applications to implement the dependency injection pattern, allowing us to write cleaner, more maintainable code for the reasons I explained in the previous section.</p>
<p><a target="_blank" href="https://www.devleader.ca/2024/02/23/scrutor-vs-autofac-in-c-what-you-need-to-know/">There are other IoC containers to help us</a> manage and resolve dependencies in our applications, including the built-in IServiceCollection, but Autofac is the one that I am most comfortable using. As .NET has evolved IServiceCollection has become more feature-rich, and with the gap in features between the two closing, Autofac is still one that I like using in my development.</p>
<h3 id="heading-what-is-the-autofacserviceproviderfactory-in-aspnet-core"><strong>What is the AutofacServiceProviderFactory in ASP.NET Core?</strong></h3>
<p>The <code>AutofacServiceProviderFactory</code> is a specific component in the Autofac library designed for integrating Autofac with the built-in dependency injection (DI) system in ASP.NET Core. Essentially, it acts as a bridge allowing you to use Autofac as the DI container instead of the default one provided by Microsoft.</p>
<p>I’ve written about this before in this article:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.devleader.ca/2024/03/19/autofac-in-asp-net-core-how-to-avoid-this-debugging-nightmare/">https://www.devleader.ca/2024/03/19/autofac-in-asp-net-core-how-to-avoid-this-debugging-nightmare/</a></div>
<p> </p>
<hr />
<h2 id="heading-exploring-a-sample-aspnet-core-application"><strong>Exploring A Sample ASP.NET Core Application</strong></h2>
<p>I wanted to make sure we had a common application to refer to when I get into more of the technical details of what we do and do not get with <code>AutofacServiceProviderFactory</code>. The following code is the sample weather app we get from Visual Studio when creating a new ASP.NET Core web API, but I’ve modified it slightly to showcase some of the behavior we get with <code>AutofacServiceProviderFactory</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;
<span class="hljs-keyword">using</span> Autofac.Extensions.DependencyInjection;

<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(<span class="hljs-keyword">new</span> AutofacServiceProviderFactory(containerBuilder =&gt;
{
    containerBuilder
        .RegisterInstance(builder)
        .SingleInstance();
    containerBuilder
        .Register(ctx =&gt; ctx.Resolve&lt;WebApplicationBuilder&gt;().Configuration)
        .SingleInstance();
    <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> we can't do this because the WebApplicationBuilder</span>
    <span class="hljs-comment">// the WebApplicationBuilder is responsible for building the</span>
    <span class="hljs-comment">// WebApplication, so we can't do that manually just to add</span>
    <span class="hljs-comment">// it into the container</span>
    <span class="hljs-comment">//containerBuilder</span>
    <span class="hljs-comment">//    .Register(ctx =&gt;</span>
    <span class="hljs-comment">//    {</span>
    <span class="hljs-comment">//        var app = ctx.Resolve&lt;WebApplicationBuilder&gt;().Build();</span>
    <span class="hljs-comment">//        app.UseHttpsRedirection();</span>
    <span class="hljs-comment">//        return app;</span>
    <span class="hljs-comment">//    })</span>
    <span class="hljs-comment">//    .SingleInstance();</span>
    containerBuilder.RegisterType&lt;DependencyA&gt;().SingleInstance();
    containerBuilder.RegisterType&lt;DependencyB&gt;().SingleInstance();
    containerBuilder.RegisterType&lt;DependencyC&gt;().SingleInstance();
    <span class="hljs-comment">//containerBuilder</span>
    <span class="hljs-comment">//    .RegisterBuildCallback(ctx =&gt;</span>
    <span class="hljs-comment">//    {</span>
    <span class="hljs-comment">//        // <span class="hljs-doctag">FIXME:</span> this was never registered</span>
    <span class="hljs-comment">//        var app = ctx.Resolve&lt;WebApplication&gt;();</span>

    <span class="hljs-comment">//        var summaries = new[]</span>
    <span class="hljs-comment">//        {</span>
    <span class="hljs-comment">//            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"</span>
    <span class="hljs-comment">//        };</span>

    <span class="hljs-comment">//        app.MapGet(</span>
    <span class="hljs-comment">//            "/weatherforecast",</span>
    <span class="hljs-comment">//            (</span>
    <span class="hljs-comment">//                [FromServices] DependencyA dependencyA // this will work</span>
    <span class="hljs-comment">//              , [FromServices] DependencyB dependencyB // <span class="hljs-doctag">FIXME:</span> this will fail!!</span>
    <span class="hljs-comment">//              , [FromServices] DependencyC dependencyC // this will work</span>
    <span class="hljs-comment">//            ) =&gt;</span>
    <span class="hljs-comment">//            {</span>
    <span class="hljs-comment">//                var forecast = Enumerable.Range(1, 5).Select(index =&gt;</span>
    <span class="hljs-comment">//                    new WeatherForecast</span>
    <span class="hljs-comment">//                    (</span>
    <span class="hljs-comment">//                        DateOnly.FromDateTime(DateTime.Now.AddDays(index)),</span>
    <span class="hljs-comment">//                        Random.Shared.Next(-20, 55),</span>
    <span class="hljs-comment">//                        summaries[Random.Shared.Next(summaries.Length)]</span>
    <span class="hljs-comment">//                    ))</span>
    <span class="hljs-comment">//                    .ToArray();</span>
    <span class="hljs-comment">//                return forecast;</span>
    <span class="hljs-comment">//            });</span>
    <span class="hljs-comment">//    });</span>
}));

<span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> we can't get the WebApplication into the</span>
<span class="hljs-comment">// Autofac container, because it's already been built.</span>
<span class="hljs-comment">// this means if we have anything that wants to take a</span>
<span class="hljs-comment">// dependency on the WebApplication instance itself, we</span>
<span class="hljs-comment">// can't resolve it from the container.</span>
<span class="hljs-keyword">var</span> app = builder.Build();
app.UseHttpsRedirection();

<span class="hljs-keyword">var</span> summaries = <span class="hljs-keyword">new</span>[]
{
    <span class="hljs-string">"Freezing"</span>, <span class="hljs-string">"Bracing"</span>, <span class="hljs-string">"Chilly"</span>, <span class="hljs-string">"Cool"</span>, <span class="hljs-string">"Mild"</span>, <span class="hljs-string">"Warm"</span>, <span class="hljs-string">"Balmy"</span>, <span class="hljs-string">"Hot"</span>, <span class="hljs-string">"Sweltering"</span>, <span class="hljs-string">"Scorching"</span>
};

app.MapGet(
    <span class="hljs-string">"/weatherforecast"</span>,
    (
        [<span class="hljs-meta">FromServices</span>] DependencyA dependencyA <span class="hljs-comment">// this will work</span>
      , [FromServices] DependencyB dependencyB <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> this will fail!!</span>
      , [FromServices] DependencyC dependencyC <span class="hljs-comment">// this will work</span>
    ) =&gt;
    {
        <span class="hljs-keyword">var</span> forecast = Enumerable.Range(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>).Select(index =&gt;
            <span class="hljs-keyword">new</span> WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(<span class="hljs-number">-20</span>, <span class="hljs-number">55</span>),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
            .ToArray();
        <span class="hljs-keyword">return</span> forecast;
    });

app.Run();

<span class="hljs-function"><span class="hljs-keyword">internal</span> record <span class="hljs-title">WeatherForecast</span>(<span class="hljs-params">DateOnly Date, <span class="hljs-keyword">int</span> TemperatureC, <span class="hljs-keyword">string</span>? Summary</span>)</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> TemperatureF =&gt; <span class="hljs-number">32</span> + (<span class="hljs-keyword">int</span>)(TemperatureC / <span class="hljs-number">0.5556</span>);
}

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyA</span>(<span class="hljs-params">
    WebApplicationBuilder _webApplicationBuilder</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyB</span>(<span class="hljs-params">
    Lazy&lt;WebApplication&gt; _webApplication</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> class <span class="hljs-title">DependencyC</span>(<span class="hljs-params">
    IConfiguration _configuration</span>)</span>;
</code></pre>
<p>You should note that I’ve modified the weather API itself to take in 3 dependencies that we want to resolve from the service list. <code>[FromService]</code> is in fact not required here, but it makes the error messages more clear if you were to go run this and want to understand where and why it fails.</p>
<p>But wait… why does it fail?! Keep on readin’ and <a target="_blank" href="https://youtu.be/pjvtZGJTqHg">follow along with this video on Autofac to find out more</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/pjvtZGJTqHg">https://youtu.be/pjvtZGJTqHg</a></div>
<p> </p>
<h3 id="heading-what-can-we-get-with-autofacserviceproviderfactory-in-aspnet-core"><strong>What Can We Get With AutofacServiceProviderFactory in ASP.NET Core?</strong></h3>
<p>Let’s start off with what we get from this setup because I do think that this is the typical path. To be clear, there’s nothing “wrong” with this approach, but you need to understand where dependencies are registered and resolved, and therefore what works with your container:</p>
<ul>
<li><p>We have access to the <code>WebApplicationBuilder</code> on the Autofac <code>ContainerBuilder</code> instance. This allows us to have services depending on the app builder instance, which means we can have modules and/or plugins that want to setup information on the app builder or otherwise read state from the app builder.</p>
</li>
<li><p>With that said, we have access to the <code>IConfiguration</code> instance from the <code>WebApplicationBuilder</code> because it’s exposed on the web app builder itself.</p>
</li>
<li><p>We get the ability to resolve dependencies from the container that are defined directly on our minimal APIs! In the example I shared above, the dependency classes A through C are all types that can be resolved from the container automatically on the minimal API. There’s a catch for one of these which we’ll cover, but the point is their registrations can be seen by our minimal API.</p>
</li>
</ul>
<p>In general, this is probably “good enough” for most situations if you just want to use Autofac for your ASP.NET Core application. However, this is limiting for the style of development that I like to do.</p>
<h3 id="heading-whats-missing-with-autofacserviceproviderfactory-in-aspnet-core"><strong>What’s Missing With AutofacServiceProviderFactory in ASP.NET Core?</strong></h3>
<p>Now that we’ve seen the goodness that we get, let’s discuss where there are some drawbacks. They’re essentially already highlighted in the code with FIXME comments, but it’s worth elaborating on them in more detail here. Again, this is not to suggest this is the “wrong” way to do it, just that you have some considerations to make:</p>
<ul>
<li><p>The <code>WebApplication</code> instance is not something that we can resolve from the container. That is, if you ever want to have classes automatically resolve from the dependency container, they cannot take a dependency on <code>WebApplication</code>. This is because this instance is never registered onto the container and therefore cannot be automatically injected for us.</p>
</li>
<li><p>We can’t overcome this behavior by calling the <code>Build()</code> method manually on the <code>WebApplicationBuilder</code> inside of an Autofac registration. This is because the chain of registrations executes once we call <code>Build()</code> on the web application builder OUTSIDE of the container, which then handles the rest of the application being built. Said another way, this creates a bit of a circular dependency on the responsibilities that need to be handled.</p>
</li>
<li><p>Because we cannot resolve the <code>WebApplication</code> instance from the dependency container, we cannot create plugins that add their own routes to the application using the minimal API route registration syntax. If this is indeed possible to do, it would have to be using a different API and instance of a different type since the <code>WebApplication</code> instance is not accessible to us via the container.</p>
</li>
<li><p>Based on the above points, we cannot have dependencies on the routes like <code>DependencyB</code> in the example above. This is because this type has a dependency on <code>WebApplication</code> and the container simply does not know about it. In the future articles, you’ll see examples of this pattern coming up again so it’s worth mentioning in this article for reference.</p>
</li>
</ul>
<p>Many of these are not a concern for folks building typical applications. However, as someone that builds mostly plugin architecture applications, this is very limiting for me!</p>
<hr />
<h2 id="heading-wrapping-up-autofacserviceproviderfactory-in-aspnet-core"><strong>Wrapping Up AutofacServiceProviderFactory in ASP.NET Core</strong></h2>
<p>In this article, I provided a brief overview of dependency injection and Autofac within ASP.NET Core. The primary takeaway was looking at what you do and do not get when using AutofacServiceProviderFactory in ASP.NET Core. While the limitations of this are minimized for the average application, this does not work well for a plugin architecture that wants to extend the API routes via plugins.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Break into Big Tech – My Journey from Startup to Microsoft]]></title><description><![CDATA[Many software engineers set their sights on getting into big tech someday — It seems like the destination to end up at in one’s career. Now this of course isn’t universally true (nor should it be) but regardless, this is a goal for many. But is Big T...]]></description><link>https://hashnode.devleader.ca/break-into-big-tech-my-journey-from-startup-to-microsoft</link><guid isPermaLink="true">https://hashnode.devleader.ca/break-into-big-tech-my-journey-from-startup-to-microsoft</guid><category><![CDATA[Career]]></category><category><![CDATA[career advice]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Startups]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 06 May 2024 12:00:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1714392514971/4eda86f1-b0e1-4fcc-96df-b2df73b86129.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Many software engineers set their sights on getting into big tech someday — It seems like <em>the</em> destination to end up at in one’s career. Now this of course isn’t universally true (nor should it be) but regardless, this is a goal for many. But is Big Tech all it’s cracked up to be? Are the stereotypes true? How the heck can someone get into these big companies?</p>
<p>In this article, I wanted to share with you my journey from working at startup companies all the way to being a Principal Software Engineering Manager at Microsoft. I’d love to share with you my interview experiences and my observations about what I value (and what I dislike) from startups and Big Tech.</p>
<p>Remember that your <a target="_blank" href="https://www.devleader.ca/2024/01/19/owning-your-career-journey-behind-the-screen-2024-january-week-3/">career journey</a> is for you to own. Don’t try to copy someone else’s life, just learn from their experiences and take charge of your own. There’s no “wrong” path. Every path is unique.</p>
<hr />
<p>I wrote this article for my good friend, <a target="_blank" href="https://www.linkedin.com/in/mwaseemzakir/">Muhammad Waseem</a>. He graciously offered to include my story <a target="_blank" href="https://mwaseemzakir.substack.com/p/ep-56-break-into-big-tech-journey">in one of his newsletters</a>, and I thought it would be such an awesome opportunity to share with his audience. My version of the article has been slightly adapted so I can share other relevant content for my own audience.</p>
<p>Muhammad, my friend, thank you for thinking about me!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-my-background"><strong>My Background</strong></h2>
<p>I went to the University of Waterloo for computer engineering. While I didn’t like my classes at all, my 6 internships really solidified that I wanted to be in this industry. I spent my internships mostly at startups or small companies, but in completely different sectors so I could get different experiences.</p>
<blockquote>
<p><em>Action: Take advantage of internships if you have the option!</em></p>
<p><em>Action: Use your internships to explore different domains and styles of companies!</em></p>
</blockquote>
<p>My first real full-time software engineering job outside of university was a digital forensics company, now called <a target="_blank" href="https://www.magnetforensics.com/">Magnet Forensics</a>, that was just starting out. This was the first time I started to have a good mix of autonomy and solid leadership mixed together because up until this point with work, I felt it hard to stay motivated in what I was doing for work.</p>
<p>This company had also taken a chance on me because they appreciated my existing skills and way of thinking but knew that I had zero experience in digital forensics. This was also going to be one of the first times in my career that I really noticed “Oh crap, I don’t know how to do any of this…” only to realize that after several months I was on my way to building expertise.</p>
<blockquote>
<p><em>Action: Find companies and leadership that you align with. This may take time and experience in industry.</em></p>
<p><em>Action: Don’t be afraid to jump into new challenges. It’s the best way to learn.</em></p>
</blockquote>
<p>I became a technical manager within several months of being at this company, which required my time was spent coding and managing. But this was all due to one critical software engineering skill that I think everyone should invest more time in: Communication.</p>
<blockquote>
<p><em>Action: Work on your</em> <a target="_blank" href="https://www.devleader.ca/2024/01/18/software-engineering-soft-skills-6-focus-areas-that-you-need/"><em>soft skills, not just your technical skills</em></a></p>
</blockquote>
<p><a target="_blank" href="https://youtu.be/AWTwji6mmeA">Check out this video with Callie Buruchara for more details on why communication is so valuable</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/AWTwji6mmeA">https://youtu.be/AWTwji6mmeA</a></div>
<p> </p>
<hr />
<h2 id="heading-getting-into-big-tech"><strong>Getting into Big Tech</strong></h2>
<p>This was one of my least favorite things I’ve done in the past few years. I find that I don’t do a great job selling myself to recruiters, and it feels unnatural to discuss my accomplishments. I needed to spend time updating my resume, which would include <a target="_blank" href="https://www.devleader.ca/2024/01/06/brag-documents-highlight-trackers-take-control-of-your-career-progression/">highlighting some of the biggest accomplishments in my career</a> up to this point.</p>
<blockquote>
<p><em>Action: Update your resume with high impact work. Pick relevant experiences to what you’re applying for.</em></p>
</blockquote>
<p>I applied to some of the popular Big Tech companies and after several <a target="_blank" href="https://www.devleader.ca/2024/03/30/actionable-interview-tips-dev-leader-weekly-37/">weeks had interviews</a> that were lined up over a few weeks. In order to do this, I chose the route of going onto their career pages and going through the typical paths. I felt that I had solid work experience and based on historically what I had heard, it shouldn’t be too difficult to hear back.</p>
<blockquote>
<p><em>Action: Most (if not all) companies have career pages that show you what they are actively hiring for. Use those.</em></p>
</blockquote>
<p>Admittedly, the job market now is extremely different than it was when I was applying. You need to do everything you can to stand out. This may be an EXTREMELY difficult time to apply to Big Tech companies because of the volume of people trying — so I do not want you to be discouraged. It may not currently be in your favor, but that doesn’t mean you can’t focus on things that are in your control.</p>
<blockquote>
<p><em>Action: Give some consideration to companies that aren’t Big Tech. They can offer incredible opportunities and there’s less competition.</em></p>
</blockquote>
<p>Networking can be very powerful — so get in touch with recruiters as much as you can. You may have luck connecting with hiring managers, but from my personal experience, I have to direct every single person to the Microsoft careers page anyway.</p>
<blockquote>
<p><em>Action: Always try to be networking! Build relationships with recruiters!</em></p>
</blockquote>
<p>With that said, if you’re interested in Microsoft, my biggest advice would be to:</p>
<ul>
<li><p>Use <a target="_blank" href="https://careers.microsoft.com/v2/global/en/home.html">the Microsoft careers page</a> to find jobs you’re interested in</p>
</li>
<li><p>Use LinkedIn to connect with recruiters</p>
</li>
<li><p>Use LinkedIn to connect with employees in the space</p>
</li>
</ul>
<p>When you connect with the employees in the space DO NOT ask them to refer you. They don’t even know you, so they should not be referring you. Instead, see if you can get some time from them to <a target="_blank" href="https://www.devleader.ca/2023/09/27/workplace-based-learning-how-to-balance-learning-at-work-vs-home/">learn about what it’s like working</a> in that space. Build a true connection and use it as a learning opportunity.</p>
<hr />
<h3 id="heading-interviewing-exactly-what-youd-expect"><strong>Interviewing – Exactly What You’d Expect</strong></h3>
<p>I’m an <a target="_blank" href="https://www.devleader.ca/2023/03/13/hands-on-management-how-to-lead-engineers-to-success/">engineering manager and I was applying for engineering manager</a> roles… But you bet that I was still being interviewed like a Principal-level software <a target="_blank" href="https://www.devleader.ca/2023/03/13/hands-on-management-how-to-lead-engineers-to-success/">engineer AND with management</a> components added in. There are many similarities with how I would be interviewed compared to an individual contributor software engineer!</p>
<p>I was grinding LeetCode questions every day. Systems <a target="_blank" href="https://www.devleader.ca/2023/12/13/what-is-the-adapter-design-pattern-beginner-questions-answered/">design questions</a>. Behavioral questions. All of it. Every day for multiple hours. This was extreme for me because I hadn’t interviewed in nearly a DECADE. And every single big tech company was similar. Algorithms. Systems design. Behavioral. Much of what you read or hear online about this is spot on.</p>
<blockquote>
<p><em>Action: Familiarize yourself with coding questions (LeetCode), distributed</em> <a target="_blank" href="https://www.devleader.ca/2023/12/13/what-is-the-adapter-design-pattern-beginner-questions-answered/"><em>design questions, and project/behavioral questions</em></a></p>
<p><em>Action: Set aside time to practice as much as you can.</em></p>
</blockquote>
<p>You need to be prepared to ask clarifying questions in the technical part. I hate these types of technical interview questions because I’ve seen people practice them like crazy, get hired, and then struggle as a developer because they just managed to train themselves well at interviewing. Something to keep in mind.</p>
<blockquote>
<p><em>Action: When you’re practicing, try verbally asking clarifying questions and give yourself some constraints. You need to get good at this.</em></p>
</blockquote>
<p>I only had one of my interviews, but that’s okay. It can happen to anyone. Ultimately, I chose Microsoft because everything I had heard about the work culture was aligned with what I wanted.</p>
<p>These two livestreams focus on getting noticed and preparing for interviews, and I think they’re very valuable to go alongside this:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/7EIcqeNeTGA">https://youtu.be/7EIcqeNeTGA</a></div>
<p> </p>
<p>And the second one focusing on the interview process itself, here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/6ckNmAAtjs8">https://youtu.be/6ckNmAAtjs8</a></div>
<p> </p>
<hr />
<h2 id="heading-big-tech-final-thoughts"><strong>Big Tech – Final Thoughts</strong></h2>
<p>I want to close out this article by bringing back what I said in the introduction:</p>
<p>There’s no “wrong” path. Every path is unique.</p>
<p>My philosophy in software engineering is that there are pros and cons to everything. Where we work is no different. Some similarities and differences from my own experiences:</p>
<ul>
<li><p>You might be working on platforms and/or internal systems compared to user-facing offerings. Figure out what you prefer!</p>
</li>
<li><p>You can find a lot of meaning in what you’re doing at big or small companies, but it’s often easier to feel that you have a bigger relative impact at a smaller company</p>
</li>
<li><p>How much autonomy you have can vary from company to company — usually smaller companies there’s more flexibility and autonomy because there’s less bureaucracy built in.</p>
</li>
<li><p>From team to team, or company to company, you might notice the rate at which you can ship features/fixes is different. This can be a VERY big quality of life to consider as a software engineer.</p>
</li>
<li><p>Big tech has very ironed out career ladders whereas startups it can be more chaotic — but your level vs how much REAL experience you gain are not always aligned.</p>
</li>
<li><p>How you interview for Big Tech is well documented but for startups and smaller companies the interview processes may look quite different</p>
</li>
</ul>
<p>There are many more things to compare — but I want you to know that many people will value these things differently. What we value in life changes as well. I’m very respectful of my work-life time boundaries now. No more 16-hour days.</p>
<p>But a question I’d leave you with is… What do you truly value in your career? In your life?</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[MudBlazor with Blazor SSR – What You Need To Know]]></title><description><![CDATA[This is yet another selfish guide! I’m writing this to help my future self with having MudBlazor with Blazor interactive SSR working within a new project. Of course, the positive side effect is that you get to benefit from this guide too! Maybe it wa...]]></description><link>https://hashnode.devleader.ca/mudblazor-with-blazor-ssr-what-you-need-to-know</link><guid isPermaLink="true">https://hashnode.devleader.ca/mudblazor-with-blazor-ssr-what-you-need-to-know</guid><category><![CDATA[Blazor]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[ASP.NET]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Wed, 01 May 2024 12:00:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713960514320/9ee39264-e83f-4eb3-bb48-375b217b7783.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is yet another selfish guide! I’m writing this to help my future self with having MudBlazor with Blazor interactive SSR working within a new project. Of course, the positive side effect is that you get to benefit from this guide too! Maybe it wasn’t so selfish after all, right?!</p>
<p>This guide will focus on getting MudBlazor with Blazor interactive SSR set up and configured in a new Blazor project in dotnet 8. This is hopefully applicable for future versions of dotnet, as long as this doesn’t change behavior dramatically. Following this guide will ideally prevent you from running into <a target="_blank" href="https://www.devleader.ca/2024/03/21/blazor-render-mode-how-to-avoid-dependency-injection-woes/">all sorts of fun Blazor render mode issues</a>.</p>
<hr />
<h2 id="heading-what-is-mudblazor"><strong>What is MudBlazor?</strong></h2>
<p>Like with all user-interface tech stacks, it’s very common to have reusable control libraries. One such control library is <a target="_blank" href="https://mudblazor.com/">MudBlazor</a>. In their own words:</p>
<blockquote>
<p><em>MudBlazor is an ambitious Material Design component framework for Blazor with an emphasis on ease of use and clear structure. It is perfect for .NET developers who want to rapidly build web applications without having to struggle with CSS and Javascript. MudBlazor, being written entirely in C#, empowers you to adapt, fix or extend the framework. There are plenty of examples in the documentation, which makes understanding and learning MudBlazor very easy.</em></p>
</blockquote>
<p>Originally, I went looking for MudBlazor because I wanted to develop more of a <a target="_blank" href="https://www.devleader.ca/2024/03/20/mudblazor-list-items-how-to-create-awesome-blazor-list-views/">customized list view in my application</a>. However, the default controls didn’t seem like they did a great job for what I wanted. I’ve spent well over a decade building user interface applications in WinForms and WPF, so I’m no stranger to control libraries. But that’s exactly why I figured I shouldn’t need to roll my own — someone else has got this covered!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-what-are-blazor-render-modes"><strong>What Are Blazor Render Modes?</strong></h2>
<p>Blazor Web Apps use different render modes to control where and how components are rendered. The modes include:</p>
<ol>
<li><p><strong>Static Server</strong>: Renders components on the server without interactivity.</p>
</li>
<li><p><strong>Interactive Server</strong>: Also renders on the server but allows interactivity using Blazor Server.</p>
</li>
<li><p><strong>Interactive WebAssembly</strong>: Renders interactively on the client-side using Blazor WebAssembly.</p>
</li>
<li><p><strong>Interactive Auto</strong>: Starts with server-side rendering and shifts to client-side on subsequent interactions after the Blazor bundle is downloaded.</p>
</li>
</ol>
<p>These render modes are set using the <code>@rendermode</code> directive in the component’s code. More details on configuring and applying these modes can be found on the <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0">Microsoft documentation page</a>.</p>
<p>This article is not focusing on which render mode is better or worse, nor will I be doing an in-depth analysis. I wanted to provide this context so that you can see we’ll be using Interactive Server render mode to get Blazor server-side rendering (SSR) with our app.</p>
<p>With that said, the distinction between client-side and server-side rendering is important for performance and interactivity:</p>
<ul>
<li><p><strong>Client-side rendering</strong> (WebAssembly mode): Components are executed and rendered directly in the user’s browser using WebAssembly. This mode offers a richer, more interactive experience as it doesn’t require a round-trip to the server for UI updates. However, it involves a larger initial download and more resource consumption on the client side.</p>
</li>
<li><p><strong>Server-side rendering</strong> (Server mode): Components are executed and rendered on the server. The rendered UI is delivered as static HTML to the client’s browser, and interactivity is maintained through a SignalR connection that manages event handling and UI updates. This mode minimizes client-side resources since the client doesn’t execute the component logic, but it relies heavily on the network connection to the server, which can impact responsiveness and user experience.</p>
</li>
</ul>
<p>Each mode has its use case depending on the application’s needs for performance, scalability, and complexity. The focus of this article is on a server rendering mode not because I claim it’s superior, but because it’s what I needed for my own development purposes.</p>
<hr />
<h2 id="heading-how-to-get-mudblazor-with-blazor-interactive-ssr-working"><strong>How to Get MudBlazor with Blazor Interactive SSR Working</strong></h2>
<p>The following sections will give you the step-by-step actions required to get MudBlazor with Blazor interactive SSR working. You can follow along with <a target="_blank" href="https://www.youtube.com/watch?v=TxLc7cauJRg">this MudBlazor video tutorial as well</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=TxLc7cauJRg">https://www.youtube.com/watch?v=TxLc7cauJRg</a></div>
<p> </p>
<h3 id="heading-new-blazor-project-setup"><strong>New Blazor Project Setup</strong></h3>
<p>The first thing that we need to do is create our project in Visual Studio. To do that, we’re going to select the “Blazor Web App” project template from Visual Studio.</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/blazor-web-app-new-project-1024x710.webp" alt="MudBlazor with Blazor SSR - New Blazor Web App" /></p>
<p>Next, we’ll want to ensure we select the correct render mode. We want it to be “Server” as we see in the screenshot below.</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/blazor-web-app-server-render-mode-1024x719.webp" alt="MudBlazor with Blazor SSR - Server Render Mode" /></p>
<p>The other options are of course up to you. If indeed you need another render mode, then the rest of this guide is not for you as we’re strictly focused on server-side render (SSR) mode. Remember, the reason that I wrote this is that I thought I <em>had</em> to use the dual mode for supporting MudBlazor because the instructions I received didn’t seem to line up exactly.</p>
<h3 id="heading-configuring-mud-blazor-with-blazor-interactive-ssr"><strong>Configuring Mud Blazor with Blazor Interactive SSR</strong></h3>
<p>Now that we have our project setup, it’s time to get going with setting up MudBlazor. I should note that they DO have instructions that you can follow <a target="_blank" href="https://github.com/MudBlazor/MudBlazor">on their GitHub</a> — so if you’re getting stuck with my guide, go read theirs. However, I followed theirs the first time and still ran into some fun hiccups because I didn’t know what project to create. Not the fault of MudBlazor nor the fault of Blazor; Just Nick’s fault.</p>
<p>Step one will be getting the nuget package installed:</p>
<pre><code class="lang-csharp">dotnet <span class="hljs-keyword">add</span> package MudBlazor
</code></pre>
<p>And once installed, we only have a couple of spots to go update! Starting off, to make the MudBlazor accessible in our razor files by default, we can add the following to <code>_Imports.razor</code>:</p>
<pre><code class="lang-csharp">@using MudBlazor
</code></pre>
<p>Slightly separate guidance from what they list on their GitHub, but we can place the following code in the &lt;head&gt; block of App.razor</p>
<pre><code class="lang-csharp">&lt;link href=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&amp;display=swap"</span> rel=<span class="hljs-string">"stylesheet"</span> /&gt;
&lt;link href=<span class="hljs-string">"_content/MudBlazor/MudBlazor.min.css"</span> rel=<span class="hljs-string">"stylesheet"</span> /&gt;
&lt;MudThemeProvider/&gt;
&lt;MudDialogProvider/&gt;
&lt;MudSnackbarProvider/&gt;
</code></pre>
<p>Next, we add the following to the &lt;body&gt; block of the same file:</p>
<pre><code class="lang-csharp">&lt;script src=<span class="hljs-string">"_content/MudBlazor/MudBlazor.min.js"</span>&gt;&lt;/script&gt;
</code></pre>
<p>And finally, we need these two lines into program.cs to enable dependency injection for MudBlazor:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> MudBlazor.Services;
builder.Services.AddMudServices();
</code></pre>
<hr />
<h2 id="heading-using-mudblazor-with-blazor-interactive-ssr"><strong>Using MudBlazor with Blazor Interactive SSR</strong></h2>
<p>Now that we’re all configured, we can use MudBlazor! I started off with the sample application to prove this all out, so I figured I’d change the default “counter” page to use MudBlazor controls.</p>
<p>Here’s the change to that code that I made:</p>
<pre><code class="lang-csharp">@page <span class="hljs-string">"/counter"</span>

&lt;PageTitle&gt;Counter&lt;/PageTitle&gt;

&lt;h1&gt;Counter&lt;/h1&gt;

&lt;MudText Typo=<span class="hljs-string">"Typo.h6"</span>&gt;
    Current count: @currentCount
&lt;/MudText&gt;
&lt;MudButton
    Variant=<span class="hljs-string">"Variant.Filled"</span> 
    Color=<span class="hljs-string">"Color.Primary"</span> 
    OnClick=<span class="hljs-string">"ButtonOnClick"</span>&gt;
    Click Me!
&lt;/MudButton&gt;

@code 
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> currentCount = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">ButtonOnClick</span>(<span class="hljs-params"></span>)</span>
    {
        currentCount++;
    }
}
</code></pre>
<p>And if you want to see it in action:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/mudblazor-counter-page-1024x607.webp" alt="MudBlazor with Blazor SSR - Counter Page" /></p>
<hr />
<h2 id="heading-wrapping-up-mudblazor-with-blazor-interactive-ssr"><strong>Wrapping Up MudBlazor with Blazor Interactive SSR</strong></h2>
<p>This was just a simple guide to get you up and running using MudBlazor with Blazor interactive SSR! If you start off with the Blazor server-side rendering project instead of the dual mode where it’s auto server and webassembly, you’ll have a much better time. However, maybe you know what you’re doing significantly better than me and you’re ready to jump into the dual render-mode support — but I certainly was not!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Try Catch in C#: The Basics You Need to Know]]></title><description><![CDATA[As much as we’d like to write perfect programs, there’s going to be a point where you need to think about handling error cases in your C# applications. That’s why you’re here: for an introduction to try catch in C#!
In this article, I’ll explain the ...]]></description><link>https://hashnode.devleader.ca/try-catch-in-c-the-basics-you-need-to-know</link><guid isPermaLink="true">https://hashnode.devleader.ca/try-catch-in-c-the-basics-you-need-to-know</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[error handling]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Tue, 30 Apr 2024 12:00:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713874127102/f56a419a-23c8-49c8-8e2d-71c0f6443631.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As much as we’d like to write perfect programs, there’s going to be a point where you need to think about handling error cases in your C# applications. That’s why you’re here: for an introduction to try catch in C#!</p>
<p>In this article, I’ll explain the very basics of how to structure try catch blocks and what each block is responsible for. The code is simple and aims to help explain some of the basic <a target="_blank" href="https://www.devleader.ca/2024/02/22/c-for-beginners-5-simplified-concepts-in-c/">concepts to beginners</a> working in C#. If that sounds like you, read on!</p>
<hr />
<h2 id="heading-overview-of-exception-handling-in-c"><strong>Overview of Exception Handling in C#</strong></h2>
<p>Let’s face it: there are going to be exceptions in our C# applications and services at some point. We hate to admit it, but it’s a reality that we have to understand how to work with.</p>
<p>Exception handling in C# is done by using what’s called a try/catch block. So try catch in C# is how we set up code to have some type of protection and define the logic for how we want to deal with those exceptions.</p>
<p>The following sections will explain the two main pieces, try and catch, and later on we’ll see an extra third component we can add to the try catch blocks we create in C#. You can follow along with <a target="_blank" href="https://youtu.be/rofX_tAF7e4">this video on how to handle exceptions with try/catch blocks in C# as well</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/rofX_tAF7e4">https://youtu.be/rofX_tAF7e4</a></div>
<p> </p>
<h3 id="heading-the-try-block"><strong>The Try Block</strong></h3>
<p>The try block is the first important part of our exception handling that we need to look at. It serves the purpose of enclosing the code that might potentially throw an exception. By placing the code within a try block, we ensure that any exceptions that occur can be caught and handled appropriately — but it’s not handled by this block, this block just tells us what will get handled.</p>
<p>The try block is structured using the keyword “try”, followed by a set of curly braces that contain the code we want to monitor for exceptions. This code is often referred to as the “protected code”, as it is within this block that we anticipate will be potentially throwing exceptions. Here’s an example of a try block in C#:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-comment">// Code that might throw an exception</span>
    <span class="hljs-keyword">int</span> result = Divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>);
    Console.WriteLine(<span class="hljs-string">"The result is: "</span> + result);
}
</code></pre>
<p>In this example, we have a function called “Divide” that takes two integers as parameters and attempts to perform a division operation. However, if the second parameter is zero, it will throw a divide by zero exception. By enclosing this code within a try block, we can catch and handle this exception appropriately — but we need another block to actually handle it! And that’s where we’re headed in the next section!</p>
<h3 id="heading-the-catch-block"><strong>The Catch Block</strong></h3>
<p>The main purpose of the catch block is to provide a mechanism for handling exceptions gracefully. The try block allows us to define what we want to protect, and the catch block allows us to define what we’ll handle and how we’ll handle it.</p>
<p>When an exception is thrown, the catch block allows us to specify the actions to be taken in response to that exception. These actions could include logging the exception, displaying an error message to the user, or taking any other necessary corrective measures. The choice is yours!</p>
<p>To catch a specific type of exception, we use the catch keyword followed by the exception type we want to handle. This allows us to handle different exceptions in different ways, tailoring our response based on the specific type of exception.</p>
<p>Here’s an example of a catch block that handles a specific exception type, in this case, the <code>DivideByZeroException</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-keyword">int</span> result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>; <span class="hljs-comment">// This will throw a DivideByZeroException</span>
}
<span class="hljs-keyword">catch</span> (DivideByZeroException ex)
{
    Console.WriteLine(<span class="hljs-string">"An error occurred: "</span> + ex.Message);
}
</code></pre>
<p>In this example, the code within the try block attempts to divide the number 10 by 0, which will result in a <code>DivideByZeroException</code>. The catch block catches this exception and executes the code within its block, which in this case, simply writes an error message to the console, displaying the message provided by the exception.</p>
<p>You can also use a base exception class or omit the exception portion altogether to catch all (well, almost all) exceptions:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
}
<span class="hljs-keyword">catch</span> (Exception ex)
{
    <span class="hljs-comment">// this will catch all catchable exceptions</span>
}

<span class="hljs-comment">// OR</span>

<span class="hljs-keyword">try</span>
{
}
<span class="hljs-keyword">catch</span>
{
    <span class="hljs-comment">// note that we don't have an exception instance in this case!</span>
}
</code></pre>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-handling-multiple-exceptions"><strong>Handling Multiple Exceptions</strong></h2>
<p>If one exception can be thrown from a called piece of code, odds are that many can. As a result, it’s common to encounter scenarios where multiple types of exceptions can occur within a single try block. These exceptions may arise due to different errors or exceptional situations that need to be handled appropriately. In this section, I’ll discuss how to handle multiple exceptions by using either multiple catch blocks or a single catch block with multiple exception types. Let’s see how!</p>
<h3 id="heading-multiple-catch-blocks-approach"><strong>Multiple Catch Blocks Approach</strong></h3>
<p>When handling multiple exceptions, one approach is to use multiple catch blocks. Each catch block is responsible for handling a specific type of exception. By using this approach, you can specify separate code blocks to handle different exceptions based on their respective types.</p>
<p>Here is an example that demonstrates the multiple catch blocks approach:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-comment">// Code that may throw exceptions</span>
}
<span class="hljs-keyword">catch</span> (ArgumentNullException ex)
{
    <span class="hljs-comment">// Handle ArgumentNullException</span>
}
<span class="hljs-keyword">catch</span> (DivideByZeroException ex)
{
    <span class="hljs-comment">// Handle DivideByZeroException</span>
}
<span class="hljs-keyword">catch</span> (FormatException ex)
{
    <span class="hljs-comment">// Handle FormatException</span>
}
</code></pre>
<p>In the above example, the catch block following the try block will catch and handle any <code>ArgumentNullException</code> that occurs. Similarly, the catch blocks for <code>DivideByZeroException</code> and <code>FormatException</code> will handle their respective exceptions.</p>
<h3 id="heading-single-catch-block-with-when-filtering"><strong>Single Catch Block with When Filtering</strong></h3>
<p>Another approach for handling multiple exceptions is to use a single catch block that can handle multiple exception types. This approach can be useful when you want to handle multiple exceptions in the same way without writing separate catch blocks for each one.</p>
<p>Here is an example that demonstrates the single catch block approach:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-comment">// Code that may throw exceptions</span>
}
<span class="hljs-keyword">catch</span> (Exception ex) <span class="hljs-keyword">when</span> <span class="hljs-comment">// look at this fancy keyword!</span>
(
    ex <span class="hljs-keyword">is</span> ArgumentNullException ||
    ex <span class="hljs-keyword">is</span> DivideByZeroException || 
    ex <span class="hljs-keyword">is</span> FormatException
)
{
    <span class="hljs-comment">// Handle ArgumentNullException, DivideByZeroException, and FormatException</span>
}
</code></pre>
<p>In the above example, the catch block will handle any <code>ArgumentNullException</code>, <code>DivideByZeroException</code>, or <code>FormatException</code> that occurs within the try block. This is because we’ve placed a filter onto the exception handler using the <code>when</code> keyword!</p>
<p>I should note that you can do more filtering than just type-checking with the when keyword. You’re able to examine the different properties for the exception instance and create filters accordingly. If you needed to filter by a certain exception message or error code on a particular exception type, you can do that with the <code>when</code> keyword.</p>
<hr />
<h2 id="heading-the-finally-block"><strong>The Finally Block</strong></h2>
<p>The finally block in C# is used to define a section of code that will always be executed, regardless of whether an exception occurred or not. Its purpose is to ensure that certain tasks, such as releasing resources or performing cleanup operations, are always carried out, regardless of the outcome of the try block.</p>
<p>The finally block is executed after the try and catch blocks, whether an exception is thrown or not. It’s written with the keyword “finally” followed by a set of curly braces {}. Any code within these braces will be executed immediately after the catch block finishes.</p>
<h3 id="heading-finally-block-use-case"><strong>Finally Block Use Case</strong></h3>
<p>One common use case for the finally block is to release any resources that were acquired within the try block. This could include closing file handles, database connections, network sockets, or any other resource that needs to be freed up. By placing the cleanup code in the finally block, you can ensure that it will be executed even if an exception is thrown in the try block.</p>
<p>Here is an example that demonstrates the use of the finally block for resource cleanup:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-comment">// Code that could potentially throw an exception</span>
    <span class="hljs-comment">// Acquiring resources</span>
    <span class="hljs-comment">// Performing operations</span>
}
<span class="hljs-keyword">catch</span>(Exception ex)
{
    <span class="hljs-comment">// Exception handling code</span>
    <span class="hljs-comment">// Logging or displaying error messages</span>
}
<span class="hljs-keyword">finally</span>
{
    <span class="hljs-comment">// Code to release resources</span>
    <span class="hljs-comment">// Closing file handles, database connections, etc.</span>
}
</code></pre>
<p>In this example, if an exception is thrown in the try block, the program flow will jump to the catch block to handle the exception. However, regardless of whether an exception is thrown or not, the code within the finally block will always be executed afterwards. This ensures that any acquired resources are properly released, preventing resource leaks and maintaining the stability of the program.</p>
<h3 id="heading-alternative-to-finally-blocks-idisposable"><strong>Alternative to Finally Blocks: IDisposable</strong></h3>
<p>The finally block that we can use when it comes to try catch in C# is very helpful — but try/catch syntax is already a bit clunky to begin with. It’s a common pattern that we want to clean up resources and if we’re being defensive, we want to make sure that we clean them up even when we have error scenarios.</p>
<p>We can use the <code>IDisposable</code> interface and a using block to help support this. So instead of requiring a finally block to clean things up, you could have code inside of a <code>Dispose()</code> method on the object that implements <code>IDisposable</code>. The code would be simplified to this:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> : <span class="hljs-title">IDisposable</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Dispose</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> do your cleanup... same </span>
        <span class="hljs-comment">// stuff that you might have wanted</span>
        <span class="hljs-comment">// in your finally block!</span>
    }
}

<span class="hljs-keyword">using</span> (Myclass myClass = <span class="hljs-keyword">new</span>())
{
    <span class="hljs-comment">// do stuff with myClass</span>
}

<span class="hljs-comment">// dispose runs after we leave the block</span>
</code></pre>
<p>This is a lot less clunky, in my opinion than a whole try/finally block to support cleanup — but of course, this will not catch errors just ensure you can still run cleanup code. We can simplify this further with implicit using now where the <code>Dispose()</code> method runs when the variable goes out of scope:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">SomeMethod</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-comment">// implicit using...</span>
    <span class="hljs-keyword">using</span> Myclass myClass = <span class="hljs-keyword">new</span>();

    <span class="hljs-comment">// do stuff with myClass</span>

    <span class="hljs-comment">// dispose runs at the end here since the variable goes out of scope</span>
}
</code></pre>
<hr />
<h2 id="heading-considerations-for-try-catch-in-c"><strong>Considerations for Try Catch in C#</strong></h2>
<p>Now that you’ve seen several different ways we can use try catch in C# as well as some different use cases, let’s talk about some considerations. We’ve seen the tools we have to use, but some guidance on using them appropriately seems fitting:</p>
<ol>
<li><p>Is it REALLY exceptional?: Consider if the exception you’re catching is truly exceptional. Unfortunately, many libraries and programs have exceptions thrown that are not truly exceptional behavior for an application. This can complicate logic and slow things down. So if you don’t need to throw them, don’t. But you also might need to catch them because you don’t want the entire program to terminate.</p>
</li>
<li><p>Catch All vs Catch Specific: Many people frown upon using a try/catch block that attempts to catch all exceptions. The argument is that you could be masking an underlying problem with a blanket handler. However, there are absolutely situations (many of which I’ve used in a professional setting) where we’ve been better off with a catch-all. Some things we are calling are outside of our control with respect to the errors they throw, and if you don’t need your entire application or service to end… then you need to handle them.</p>
</li>
<li><p>Proper Cleanup: Consider if you need something like a finally block or to use the dispose pattern. Remember, using the dispose pattern can help clean up the code but alone it does not prevent exceptions from being thrown.</p>
</li>
<li><p>Logging &amp; Telemetry: You’ll not only want to understand recovery patterns when using try catch in C#, but you should consider if you need to be doing something with this error information. If you have a live service running in production, there are many cases where you’ll want to know what’s going wrong or what can be improved. Logging and telemetry can help!</p>
</li>
</ol>
<hr />
<h2 id="heading-wrapping-up-try-catch-in-c"><strong>Wrapping Up Try Catch in C#</strong></h2>
<p>Now you’ve had a chance to see the basics of try catch in C#! I’ve aimed to help familiarize you with the purpose of the different blocks, and introduced the finally block as well! With some basic code examples to refer to along with some extra considerations to keep in mind when programming, you’re all set to start catching exceptions in your code!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Convert a String to Byte Array in C#: Encoding and Decoding Simplified]]></title><description><![CDATA[In programming, it’s very common that we need to go between strings and bytes. Humans read strings. Computers read bytes. As a result, it’s important for us dotnet developers to understand how to convert a string to a byte array in C#. We accomplish ...]]></description><link>https://hashnode.devleader.ca/how-to-convert-a-string-to-byte-array-in-csharp-encoding-and-decoding</link><guid isPermaLink="true">https://hashnode.devleader.ca/how-to-convert-a-string-to-byte-array-in-csharp-encoding-and-decoding</guid><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[C#]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 29 Apr 2024 12:00:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713701323397/5c0b9f6e-bd78-48e8-bbb2-7bf2f62ccd26.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In programming, it’s very common that we need to go between strings and bytes. Humans read strings. Computers read bytes. As a result, it’s important for us dotnet developers to understand how to convert a string to a byte array in C#. We accomplish this through a process called encoding and decoding to go back and forth between the two.</p>
<p>In this article, I’ll provide you code examples to be able to convert a string to a byte array in C# — and back again! You’ll also learn about some of the nuances of character encodings to look out for!</p>
<hr />
<h2 id="heading-encoding-and-decoding-in-c"><strong>Encoding and Decoding in C#</strong></h2>
<p>If we want to convert a string to a byte array — or go the other way — we need to understand the concept of encoding and decoding. In software engineering, encoding refers to the process of transforming a string into a sequence of bytes, while decoding involves the reverse process of transforming bytes back into a string. Simple, right?</p>
<p>Remember that strings are a sequence of characters, and the concept of a character makes a lot of sense to us as readers, but computers understand bytes. Characters themselves can be represented by numbers in computers so when we want to work with strings at a lower level, such as when sending data over a network or storing it in a file, we need to convert the string into a byte array.</p>
<p>Encoding comes into play when converting strings to byte arrays. It determines <strong>how</strong> the characters in the string are represented as bytes. The <a target="_blank" href="https://www.devleader.ca/2023/09/19/ascii-vs-utf8-how-to-navigate-character-encoding/">encoding scheme defines the mapping between characters</a> and their byte representations. <a target="_blank" href="https://www.devleader.ca/2023/09/19/ascii-vs-utf8-how-to-navigate-character-encoding/">Common encoding schemes include UTF-8, UTF-16, ASCII, and Unicode</a>.</p>
<p>Choosing the correct encoding is important because different encoding schemes support different sets of characters. For example, ASCII only supports the basic English alphabet (with a few more characters), while UTF-8 and UTF-16 are capable of representing characters from multiple languages and scripts. More on this later though since I know you’re eager for some code!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-choosing-an-encoding-for-string-to-byte-array-conversion"><strong>Choosing an Encoding for String to Byte Array Conversion</strong></h2>
<p>When converting strings to byte arrays in C#, one of the most important things to consider is character encoding. Character encoding determines the mapping between characters and byte values, and if you’re considering transforming data one way then you may want to put some thought into how to transform it back!</p>
<p>What’s that supposed to mean? Well, if we use a data transform — let’s say taking a string and transforming it to bytes with an ASCII encoding — if there is not a mapping of a particular character to a byte representation we lose that data in the result. Now what happens if you want to go the other way and get your byte array back to a string?</p>
<p>Data is missing!</p>
<p>In C#, there are various encodings available, including ASCII, UTF-8, and UTF-16, each with its specific characteristics and usage scenarios. Let’s explore these encodings and see how they can be used for string to byte array conversion.</p>
<h3 id="heading-ascii-encoding"><strong>ASCII Encoding</strong></h3>
<p>ASCII encoding represents characters using 7 bits, allowing for a total of 128 different characters. It’s primarily suitable for handling basic English <a target="_blank" href="https://www.devleader.ca/2023/09/19/ascii-vs-utf8-how-to-navigate-character-encoding/">characters and is more space-efficient compared to other encodings</a>. Here’s an example of converting a string to a byte array using ASCII encoding:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> text = <span class="hljs-string">"Hello, World!"</span>;
<span class="hljs-keyword">byte</span>[] asciiBytes = Encoding.ASCII.GetBytes(text);
</code></pre>
<p>In many modern applications, ASCII may not be what you’re after. This is especially true if you have users across the globe in locales that are not English. That’s not to say that ASCII <em>cannot</em> be used, but you’ll want to be careful about what data you ASCII encode so as to not lose information during the encoding transform.</p>
<p>So keep in mind that the ASCII <a target="_blank" href="https://www.devleader.ca/2023/09/19/ascii-vs-utf8-how-to-navigate-character-encoding/">character set represents characters using a 7-bit encoding</a> scheme, allowing for a total of 128 unique characters. However, with the growing need for internationalization and multilingual support, ASCII alone is insufficient to represent all characters effectively.</p>
<p>Good thing we have some other options coming right up!</p>
<h3 id="heading-utf-8-encoding"><strong>UTF-8 Encoding</strong></h3>
<p>UTF-8 encoding is a variable-length encoding scheme that can represent any Unicode character. It’s widely used for encoding text in various languages and is backward compatible with ASCII. It uses fewer bytes for representing ASCII characters but may require more bytes for non-ASCII characters. Here’s an example of converting a string to a byte array using UTF-8 encoding:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> text = <span class="hljs-string">"Привет, мир!"</span>;
<span class="hljs-keyword">byte</span>[] utf8Bytes = Encoding.UTF8.GetBytes(text);
</code></pre>
<h3 id="heading-utf-16-encoding"><strong>UTF-16 Encoding</strong></h3>
<p>UTF-16 encoding represents characters using either 2 or 4 bytes, making it capable of representing any Unicode character. It’s commonly used by applications that need to handle multilingual text or when interoperability with other systems is required. The encoding can be little-endian or big-endian, with the former being more prevalent. Here’s an example of converting a string to a byte array using UTF-16 encoding:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> text = <span class="hljs-string">"こんにちは、世界！"</span>;
<span class="hljs-keyword">byte</span>[] utf16Bytes = Encoding.Unicode.GetBytes(text);
</code></pre>
<hr />
<h2 id="heading-utf-8-encoding-vs-utf-16-encoding-whats-the-difference"><strong>UTF-8 Encoding vs UTF-16 Encoding – What’s The Difference?</strong></h2>
<p>Each of these encodings is variable width, and their size gives them different characteristics when we consider different alphabets.</p>
<p>Starting with UTF-8, it’s variable-width and backward-compatible with ASCII. In this encoding:</p>
<ul>
<li><p>ASCII characters, which are on the range U+0000 to U+007F, take only 1 byte.</p>
</li>
<li><p>In the next range, code points U+0080 to U+07FF take twice as much space at 2 bytes each.</p>
</li>
<li><p>Code points U+0800 to U+FFFF take one more byte, bringing us up to 3 bytes</p>
</li>
<li><p>And finally, code points U+10000 to U+10FFFF take 4 bytes.</p>
</li>
</ul>
<p>This can be very effective for English text because those characters will take up minimal space. However, when it comes to Asian text it’s not ideal for the exact opposite reason.</p>
<p>Because UTF-16 has code points from U+0000 to U+FFFF take 2 bytes and code points U+10000 to U+10FFFF are double that at 4 bytes, it’s not-so-great for English. It <em>does</em> happen to be better suited for Asian characters though.</p>
<p>There’s even UTF-32 encoding! This is a fixed-width encoding where all of the code points take four bytes — unlike the others I’ve mentioned which are dynamic in size. This can use much more storage than the other encodings, but because of its simplicity can be much faster to operate on.</p>
<p>Give some consideration to the alphabets you’ll need to support primarily!</p>
<hr />
<h2 id="heading-best-practices-for-string-to-byte-array-conversion"><strong>Best Practices for String to Byte Array Conversion</strong></h2>
<p>When converting strings to byte arrays in C#, it’s important to follow best practices to ensure efficiency and reliability. In this section, I’ll discuss some key best practices that you should keep in mind when performing string to byte array conversions.</p>
<h3 id="heading-error-handling-and-validation"><strong>Error Handling and Validation</strong></h3>
<p>When working with encodings, it’s important to handle potential errors and validate your data to prevent unexpected behavior in your code. Ideally, you structure the flow of your application such that you know what kind of data you’re dealing with. If you can write code to avoid errors in the first place, this is preferred!</p>
<p>We don’t want to have to rely on this but sometimes it’s outside of our control — handling errors is by using try-catch blocks. By encapsulating the conversion code within a try block, you can catch any exceptions that may occur during the conversion process and handle them gracefully. If you don’t have control over the source of the input data, this is something you might need to do for safety.</p>
<h3 id="heading-encoding-selection"><strong>Encoding Selection</strong></h3>
<p>C# provides several encoding options for converting strings to byte arrays, such as UTF-8, UTF-16, ASCII, and more. It’s important to select the appropriate encoding based on the specific requirements of your application. Consider factors such as character sets, compatibility with other systems, and performance implications when choosing the encoding.</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Example of encoding selection</span>
<span class="hljs-keyword">string</span> inputString = <span class="hljs-string">"Hello, World!"</span>;
<span class="hljs-keyword">byte</span>[] encodedBytes = Encoding.UTF8.GetBytes(inputString);
</code></pre>
<p>Just like we saw in the previous examples, after the Encoding class we get to pick the static property holding the encoding instance. If we need to select one to pass around as a variable and parameter, you can absolutely store it in a dedicated encoding reference:</p>
<pre><code class="lang-csharp">Encoding selectedEncoding = Encoding.UTF8;
SomeMethod(<span class="hljs-string">"Hello World!"</span>, selectedEncoding);
</code></pre>
<p>Selecting the wrong encoding can have big consequences for your application! This is especially true if you save data with an encoding that will lose data resolution and you can’t reverse it… so put some care into this!</p>
<hr />
<h2 id="heading-now-you-know-how-to-convert-a-string-to-byte-array-in-c"><strong>Now You Know How to Convert a String to Byte Array in C#!</strong></h2>
<p>You’re a pro now with encoding and decoding! Well, maybe not a full-on expert… but you have the basics put in front of you and some guidelines to work with. That’s a pretty good start.</p>
<p>Remember to select the right encoding for the situation you’re dealing with. Keep in mind that you can potentially lose data resolution when using the wrong encoding, and as a result, lose data forever!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[API Gateways in Zuplo – Creating an ASCII Art API]]></title><description><![CDATA[I was approached by Adrian Machado, an employee at Zuplo, for a problem I didn’t even know I had — yet. When I jumped on the call with him to walk through their product offering, I remember thinking “Holy crap — this is for me”. You see, I’m more tha...]]></description><link>https://hashnode.devleader.ca/api-gateways-in-zuplo-creating-an-ascii-art-api</link><guid isPermaLink="true">https://hashnode.devleader.ca/api-gateways-in-zuplo-creating-an-ascii-art-api</guid><category><![CDATA[APIs]]></category><category><![CDATA[API Gateway]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Azure]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Wed, 24 Apr 2024 12:00:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713539917116/e2dfd636-73e2-4e7b-9a16-7c6d47183df0.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was approached by Adrian Machado, an employee at <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>, for a problem I didn’t even know I had — yet. When I jumped on the call with him to walk through their product offering, I remember thinking “Holy crap — this is for me”. You see, I’m more than happy to code up solutions for things and build systems, but there’s a class of work that I REALLY don’t want to have to deal with. And every single time I work on a new project/product/service that’s web-facing this stuff comes up every time… And API Gateways in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> I feel like make this infinitely more easy to navigate.</p>
<p>In this article, I’m going to share with you my experiences with onboarding <a target="_blank" href="https://www.devleader.ca/2023/08/25/generate-ascii-art-a-simple-how-to-in-c/">my ASCII art generator</a> onto an API Gateway in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>. To cover all of the capabilities, I’ll need to spread this out over several articles, but this will explain how I achieved routing traffic through the gateway!</p>
<p><strong><em>Full disclosure</em></strong>: <a target="_blank" href="https://www.devleader.ca/2024/04/19/api-gateways-in-zuplo-creating-an-ascii-art-api/">Zuplo sponsored the article for my website</a>, but I wanted to share it on additional platforms because I genuinely enjoyed working with it.</p>
<hr />
<h2 id="heading-what-is-zuplo"><strong>What is Zuplo?</strong></h2>
<p><a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> is an API Management platform that places an emphasis on the Developer Experience (DevEx) for building web APIs. <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>‘s goal is to build a platform to make it fast and straightforward to build awesome APIs. Directly from them:</p>
<blockquote>
<p><em>We are trying to build a platform to make it fast and straightforward for developers to deliver a Stripe-level API experience to their users.</em></p>
<p><a target="_blank" href="https://zuplo.link/nick-gateway"><em><cite>Zuplo</cite></em></a></p>
</blockquote>
<p>It’s one thing to get the logic for an API implemented — which is where historically I shine pretty well. But building out a fully operational API that you can have users and other services relying on isn’t a trivial process — especially once you consider monetizing it. You’ll need to factor in:</p>
<ul>
<li><p>Documentation</p>
</li>
<li><p>Testing</p>
</li>
<li><p>Deployments</p>
</li>
<li><p>Monitoring</p>
</li>
</ul>
<p>Nevermind all of the other things regarding access and protection like authentication and rate limiting… The list goes on. But <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> aims to try and get you focused on what matters (what your API needs to do) so they can handle the rest.</p>
<h3 id="heading-what-is-an-api-gateway"><strong>What is an API Gateway?</strong></h3>
<p>An API Gateway is a component in many modern distributed systems, particularly — but not exclusively — in microservices architectures. It acts like the bouncer at the club of your backend services, managing and directing incoming API calls from clients to various backend services. I like to think of it like “the front door” — although it does more than that.</p>
<p>So… What exactly does that mean?</p>
<p>When you have a bunch of services, each handling a specific piece of functionality (like billing, user profiles, inventory, etc.), it’s not always ideal to have everyone on the outside of your system hitting them directly. And now you might ask, “Well… Why?”, and that’s because managing all those direct connections can get messy.</p>
<p>Think about handling authentication, rate limiting, and data transformation for each service individually. That’s where the API Gateway comes into play. These can simplify a lot of the interactions between services as well as callers to your services on the outside. The API Gateway simplifies client interactions with your service or services — like my front door analogy — providing a single entry point for all client requests.</p>
<h3 id="heading-what-does-zuplo-offer-for-api-gateways"><strong>What Does Zuplo Offer for API Gateways?</strong></h3>
<p>While this article will not be covering all of these in detail (c’mon, I need to spread out the juicy details a little bit…), here are some of the core offerings from <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> with respect to API gateways:</p>
<ul>
<li><p><a target="_blank" href="https://zuplo.com/features/api-key-management">API Key Management</a>: Zuplo allows you to add API key-based authentication to your APIs rapidly — literally in a few minutes.</p>
</li>
<li><p><a target="_blank" href="https://zuplo.com/features/rate-limiting">Rate Limiting and Throttling</a>: Zuplo’s rate-limiting functionality can work great when paired with their other features, like the API keys I just mentioned. They have ready-to-go limiting based on keys or JWTs but they also allow you to customize this further in code.</p>
</li>
<li><p><a target="_blank" href="https://zuplo.com/docs/handlers/url-forward">Routing and Forwarding</a>: With <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>, you can handle the request right at the edge server using the code you write in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> itself, you can run a lambda, or you can forward/rewrite the request!</p>
</li>
</ul>
<p>Yes, sure, these are all things that <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> didn’t invent, but using these within <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> means you don’t have to go build them from scratch — and they make it ridiculously easy for you to use.</p>
<p>But what else does their platform do for you if you’re developing APIs?</p>
<ul>
<li><p><a target="_blank" href="https://zuplo.com/docs/policies">Full Policy Library</a>: It’s actually almost ridiculous how many out-of-the-box policies are provided for what you might want to do with your API. Think of these almost like a “middleware” that you can insert inbound and outbound on your API as building blocks — which means you don’t need to go build this stuff from scratch!</p>
</li>
<li><p><a target="_blank" href="https://zuplo.com/docs/articles/dev-portal-configuration">Documentation Generation</a>: Right in the portal you’re able to configure and define documentation for your APIs, but all of the heavy lifting is done for you. Simply make your changes, customize what you want in your documentation, save and it’s automatically deployed to an easily consumable API documentation portal.</p>
</li>
<li><p><a target="_blank" href="https://zuplo.com/features/unlimited-environments">Automatic Rapid Deployments</a>: During my demo, I was blown away by just making changes in the portal, and pressing save, and everything is instantly deployed and live. Honestly, the API developer experience feels ridiculously smooth for these features because of how simple and quick these things become.</p>
</li>
</ul>
<hr />
<h2 id="heading-ascii-art-generator-via-zuplo"><strong>ASCII Art Generator Via Zuplo</strong></h2>
<p>In the following sections, I’ll walk you through how I went from my desktop C# ASCII art generator to an API endpoint on <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> that hits my server in the cloud! You can also watch <a target="_blank" href="https://youtu.be/5zdOvmAMPwk">the companion video where I explain how I got my ASCII art generator API setup with an API gateway</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/5zdOvmAMPwk">https://youtu.be/5zdOvmAMPwk</a></div>
<p> </p>
<h3 id="heading-why-an-ascii-art-generator"><strong>Why an ASCII Art Generator?</strong></h3>
<p>In 2023 I wrote an <a target="_blank" href="https://www.devleader.ca/2023/08/25/generate-ascii-art-a-simple-how-to-in-c/">article on ASCII art and how to create an ASCII art generator in C#</a>. I thought this was a fun little project, but it ended up being one of the articles that still — to this very day — drives a lot of traffic to my website. Even <a target="_blank" href="https://youtu.be/Mk8bwXIZTXg">the YouTube video</a>, which I’ll embed right after, has a thumbnail that still ranks quite high on Google!</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/ascii-art-thumbnail-1024x682.webp" alt="ASCII Art Generator in C# - Thumbnail on Google Images" /></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Mk8bwXIZTXg">https://youtu.be/Mk8bwXIZTXg</a></div>
<p> </p>
<p>This <a target="_blank" href="https://www.devleader.ca/2023/08/17/building-projects-unlock-success-as-a-beginner-programmer/">project was fun to build</a>, drove traffic to my site, and was quite self-contained with respect to the amount and complexity of code. I figured that this would be a perfect candidate to build an API for.</p>
<p>But back when I first started getting traction for this content, I really didn’t want to be bothered with building out all of the rate-limiting, auth, etc… These are all things I know can be done when <a target="_blank" href="https://www.devleader.ca/2023/10/15/how-to-build-a-personal-website-in-blazor-an-asp-net-core-tutorial/">building ASP.NET core</a> applications, but honestly, I couldn’t be bothered to invest the time.</p>
<p>But <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> changes that for me because the reality is I don’t have to invest much time at all! I mean this candidly: When Adrian from <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>o got on the call with me, I didn’t even realize I had a problem that <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> would solve until he started walking me through their offering. I realized literally while on the call that <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> is what could allow me to skip over the parts of API development that I truly just don’t want to work on!</p>
<h3 id="heading-initial-challenges-nicks-fault"><strong>Initial Challenges — Nick’s Fault!</strong></h3>
<p>Thanks to the code being very simple for ASCII art generation, I figured I’d just port everything over directly to <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>! One of the very cool features of <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> is that I can define a route’s logic RIGHT in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> using Typescript:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/zuplo-route-request-handler-1024x361.webp" alt="Zuplo Route Request Handler" /></p>
<p>It’s worth noting that just by doing that configuration, <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> will automatically go add the associated Typescript file for you:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/zuplo-route-request-handler-typescript-1024x539.webp" alt="Zuplo Route Request Handler with Typescript Code" /></p>
<p>So this is TOTALLY awesome — especially for Typescript folks. But here’s where my challenge started.</p>
<p>Because I’m dealing with images, I need a package that handle different image formats. In order to get this set up in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>, which is very doable, I have to understand a little bit more about building things in Typescript. Directly from their documentation:</p>
<blockquote>
<p><em>Additionally, you can also bundle custom modules inside of your own project. This process is does require some knowledge of node and npm, but it allows you to use any module or version of the module. To learn how to bundle your own modules, see the sample</em> <a target="_blank" href="https://github.com/zuplo/zuplo/tree/main/examples/custom-module"><em>Custom Modules on Github</em></a><em>.</em></p>
<p><a target="_blank" href="https://zuplo.com/docs/articles/node-modules"><em><cite>Zuplo</cite></em></a></p>
</blockquote>
<p>So for those of you who work with Node and you’re familiar with all of this stuff — Lucky for you, this should be trivial! For me, the easiest thing was to pivot.</p>
<p>While it would be super cool to have my API running completely on <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a>‘s edge servers, I already have machines up hosted in the cloud. It was time to turn to Azure!</p>
<h3 id="heading-deploying-a-web-service-to-azure"><strong>Deploying A Web Service to Azure</strong></h3>
<p>Fortunately for me, I already had a multi-purpose API server set up in Azure that I use for several of my other projects. It’s completely plugin-based, so any time I’d like to extend functionality and add new feature sets, I just add new plugins!</p>
<p>In this case, it was almost just as simple as copying the example code that I had from my previous article on building an ASCII art <a target="_blank" href="https://www.devleader.ca/2023/09/26/blazor-renderfragment-how-to-use-plugins-to-generate-html/">generator in C# over to a new plugin</a> namespace in my existing web app. One of the small steps I needed to take was putting the web API in place for the first time though!</p>
<p>This was an interesting opportunity though because I wasn’t writing an API in C# for end-users to hit… I was writing an API for <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> to hit! While I don’t want to write a crappy API right at my origin, I figured that at least <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> would allow me to build transforms to my API if needed.</p>
<p>Here’s a quick peek at what my code looks like on the server side:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Autofac;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;

<span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AsciiModule</span> : <span class="hljs-title">Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder builder</span>)</span>
    {
        builder
            .RegisterType&lt;AsciiArtFromUrlRequestValidator&gt;()
            .SingleInstance();
        builder
            .RegisterType&lt;AsciiArtGenerator&gt;()
            .AsImplementedInterfaces()
            .SingleInstance();
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> app = ctx.Resolve&lt;WebApplication&gt;();

                <span class="hljs-keyword">var</span> routeGroup = app.MapGroup(<span class="hljs-string">"ascii"</span>);

                <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> correct the container ordering-issue to inject properly</span>
                <span class="hljs-keyword">var</span> imageSourceFactory = ctx.Resolve&lt;IImageSourceFactory&gt;();
                <span class="hljs-keyword">var</span> asciiArtGenerator = ctx.Resolve&lt;IAsciiArtGenerator&gt;();
                <span class="hljs-keyword">var</span> asciiArtFromUrlRequestValidator = ctx.Resolve&lt;AsciiArtFromUrlRequestValidator&gt;();

                routeGroup.MapPost(
                    <span class="hljs-string">"/url"</span>,
                    <span class="hljs-keyword">async</span> (
                        [<span class="hljs-meta">FromBody</span>] AsciiArtFromUrlRequest request,
                        IHttpClientFactory httpClientFactory,
                        CancellationToken cancellationToken) =&gt;
                    {
                        <span class="hljs-keyword">if</span> (!asciiArtFromUrlRequestValidator.Validate(request).IsValid)
                        {
                            <span class="hljs-keyword">return</span> Results.BadRequest();
                        }

                        <span class="hljs-comment">// <span class="hljs-doctag">FIXME:</span> introduce further validations</span>
                        Stream imageStream;
                        <span class="hljs-keyword">try</span>
                        {
                            <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> client = httpClientFactory.CreateClient();
                            imageStream = <span class="hljs-keyword">await</span> client
                                .GetStreamAsync(request.ImageUrl, cancellationToken)
                                .ConfigureAwait(<span class="hljs-literal">false</span>);
                        }
                        <span class="hljs-keyword">catch</span>
                        {
                            <span class="hljs-keyword">return</span> Results.Problem();
                        }

                        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> imageSource = imageSourceFactory.CreateFromStream(imageStream);
                        <span class="hljs-keyword">var</span> art = asciiArtGenerator.GenerateAsciiArtFromImage(
                            imageSource,
                            AsciiGenerationOptions.Default with
                            {
                                ScaleDownFactor = request.ScaleDownFactor,
                                HorizontalStretchFactor = request.HorizontalStretchFactor
                            });

                        AsciiArtResponse response = <span class="hljs-keyword">new</span>(
                            art.Art,
                            art.Width,
                            art.Height);
                        <span class="hljs-keyword">return</span> Results.Ok(response);
                    });

                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RouteRegistrationDependencyMarker();
            })
            .SingleInstance();
    }
}
</code></pre>
<p>The code above gives us a POST route on the server that’s essentially just &lt;server&gt;/ascii/url, which takes a URL that my server can work with. I’d like to opt for switching over to an API where image bytes can be uploaded, but this seemed like an easy way to get started.</p>
<p>This isn’t going to be a full tutorial on deploying to Azure by any means but using “App Service” within Azure, I have full git-actions integration so that every time I make a commit, my application is deployed.</p>
<h3 id="heading-my-zuplo-api-is-alive"><strong>My Zuplo API is Alive!</strong></h3>
<p>Now that my own server is deployed in Azure, it’s time to rock and roll! This is where the simplicity of <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> really shines. Here’s the new route I added with URL rewriting:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/zuplo-ascii-art-route-forwarding-1024x393.webp" alt="Zuplo ASCII Art Route Forwarding" /></p>
<p>I literally only had to press the save button (not shown in the screenshot) and within about 3 seconds the test button became live for me to use. Directly from the browser, much like using Postman, I was able to send a test URL and get back some fancy ASCII art. I’ll skip the screenshot because Zuplo isn’t optimized to try rendering ASCII art for us — I know, I know… a critical flaw!</p>
<hr />
<h2 id="heading-security-between-azure-and-zuplo-api-gateway"><strong>Security Between Azure and Zuplo API Gateway</strong></h2>
<p>As I was putting all of this together, I said “Wait a sec! My server is still exposed to the Internet without ANY protection in front of it!”. This is realistically not a <em>huge</em> problem at the moment because nobody even knows the address of it. But still — I wanted to do this properly.</p>
<p>I reached out to <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> and asked “Hey, what’s your recommended way to do this?”, just in case they had more magic up their sleeves. They politely explained and mentioned that’s also <a target="_blank" href="https://zuplo.com/docs/articles/step-1-setup-basic-gateway">covered in the example getting started documentation</a>. And obviously, I read that ahead of time… we ALWAYS read the docs… right?</p>
<p>RIGHT?</p>
<p>After reading the documentation, I had one little change to make on my server, which was using a custom <a target="_blank" href="https://www.devleader.ca/2024/04/18/api-key-authentication-middleware-in-asp-net-core-a-how-to-guide/">middleware for adding API authentication</a>. By the way, if I haven’t sold you on plugin architecture before, API <a target="_blank" href="https://www.devleader.ca/2024/04/18/api-key-authentication-middleware-in-asp-net-core-a-how-to-guide/">key authentication</a> for my server was just another plugin:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ApiKeyModule</span> : <span class="hljs-title">Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder builder</span>)</span>
    {
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> app = ctx.Resolve&lt;WebApplication&gt;();
                <span class="hljs-keyword">var</span> config = ctx.Resolve&lt;IConfiguration&gt;();

                <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> ApiKeyConfigKey = <span class="hljs-string">"&lt;APP_CONFIG_KEY_HERE&gt;"</span>;
                Lazy&lt;<span class="hljs-keyword">string</span>?&gt; lazyApiKey = <span class="hljs-keyword">new</span>(() =&gt; config.GetValue&lt;<span class="hljs-keyword">string</span>&gt;(ApiKeyConfigKey));

                app.Use(<span class="hljs-keyword">async</span> (context, next) =&gt;
                {
                    <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> ApiKeyHeader = <span class="hljs-string">"&lt;HEADER_KEY_GOES_HERE&gt;"</span>;
                    <span class="hljs-keyword">if</span> (!context.Request.Headers.TryGetValue(ApiKeyHeader, <span class="hljs-keyword">out</span> <span class="hljs-keyword">var</span> apiKeyVal))
                    {
                        context.Response.StatusCode = <span class="hljs-number">401</span>;
                        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Api Key not found."</span>);
                    }

                    <span class="hljs-keyword">var</span> apiKey = lazyApiKey.Value;
                    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.Equals(apiKey, apiKeyVal, StringComparison.Ordinal))
                    {
                        context.Response.StatusCode = <span class="hljs-number">401</span>;
                        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Invalid API Key."</span>);
                    }

                    <span class="hljs-keyword">await</span> next(context);
                });

                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PostAppRegistrationDependencyMarker();
            })
            .SingleInstance();
    }
}
</code></pre>
<p>Now one more super quick change to <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> to add a policy to add my configured API key that I have on my server, and we’re done:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/zuplo-policy-set-headers-1024x764.webp" alt="Zuplo Policy Set Headers" /></p>
<hr />
<h2 id="heading-whats-next-for-api-gateways-in-zuplo"><strong>What’s Next for API Gateways in Zuplo?</strong></h2>
<p>At this point, I have a public API through <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> that can get hit, uses an API key with my own server, forwards that request, and gets the response. It’s a full end-to-end integration which I <em>would</em> have loved to do right within <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> — but my Typescript skills were mocking me. That will certainly be an exercise for the future because I think it would be awesome to have this one truly at the edge node.</p>
<p>But before I can make this API public, I still need a few more things… And I never actually accomplished them yet:</p>
<ul>
<li><p>API Documentation</p>
</li>
<li><p>Rate limiting</p>
</li>
<li><p>Authentication</p>
</li>
<li><p>Monetization!</p>
</li>
</ul>
<p>The good news is that since I have my API integrated with <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> now, a lot of what’s left is almost all drag-and-drop in their portal! I don’t suspect I’ll have to code anything inside of my own server at this point.</p>
<hr />
<h2 id="heading-wrapping-up-api-gateways-in-zuplo"><strong>Wrapping Up API Gateways in Zuplo</strong></h2>
<p>Overall, I thought this was an awesome platform to work with. Getting API Gateways in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> setup is simple and quick — it’s hard to argue with those two things. But if you consider people like me who don’t want to go hand-roll this kind of stuff per service they create, the fact that they’ve integrated so many building blocks makes this dreamy. There were policies in the catalog that made me think “Oh crap! I didn’t even consider that!”.</p>
<p>I’m looking forward to continuing to build this API out in <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> and getting it to a point where I can monetize it! So keep your eyes peeled — because you’ll soon have an ASCII art API you can integrate with. While yes, this post is sponsored by <a target="_blank" href="https://zuplo.link/nick-gateway">Zuplo</a> , I can say without a doubt their platform greatly simplifies a lot of the pain points I never enjoy dealing with when I develop.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[API Key Authentication Middleware In ASP NET Core – A How To Guide]]></title><description><![CDATA[While putting some special content together, I found myself needing to integrate API key authentication middleware into my ASP.NET Core application. I’ve written before about using custom middleware in ASP.NET, but I’ve also been trying to do a bette...]]></description><link>https://hashnode.devleader.ca/api-key-authentication-middleware-in-asp-net-core-a-how-to-guide</link><guid isPermaLink="true">https://hashnode.devleader.ca/api-key-authentication-middleware-in-asp-net-core-a-how-to-guide</guid><category><![CDATA[authentication]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[software development]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Tue, 23 Apr 2024 12:00:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713442117322/b159d008-6508-43fd-96f3-a042dc151736.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While putting some special content together, I found myself needing to integrate API key authentication middleware into my ASP.NET Core application. <a target="_blank" href="https://www.devleader.ca/2024/01/31/custom-middleware-in-asp-net-core-how-to-harness-the-power/">I’ve written before about using custom middleware in ASP.NET</a>, but I’ve also been trying to do a better job of documenting smaller code changes like this so the next time I’m looking I have an easy reference.</p>
<p>And that means YOU get some free code and a reference guide to go along with it!</p>
<hr />
<h2 id="heading-what-is-middleware-in-aspnet-core"><strong>What is Middleware in ASP.NET Core?</strong></h2>
<p>Middleware in ASP.NET Core is code that you can add into an application’s pipeline to handle requests and responses. Each of these components can:</p>
<ul>
<li><p>Choose whether to pass the request to the next component in the pipeline</p>
</li>
<li><p>Can perform work before and after the next component in the pipeline.</p>
</li>
</ul>
<p>When building an ASP.NET Core application, middleware can be used to implement functionality such as authentication, error handling, logging, and serving static files. The list goes on, and you can even <a target="_blank" href="https://www.devleader.ca/2024/01/31/custom-middleware-in-asp-net-core-how-to-harness-the-power/">implement your own custom middleware</a>. If you’d like more information on middleware to get started, you can check out this article that I’ve written:</p>
<ul>
<li><a target="_blank" href="https://www.devleader.ca/2024/01/31/custom-middleware-in-asp-net-core-how-to-harness-the-power/">Custom Middleware in ASP.NET Core – How to Harness the Power!</a></li>
</ul>
<p>For our use case here, we’ll be looking at adding our own <a target="_blank" href="https://www.devleader.ca/2024/01/31/custom-middleware-in-asp-net-core-how-to-harness-the-power/">custom middleware</a> to an ASP.NET Core application. Given that we want to do some type of authentication with an API key, we should be able to create middleware that STOPS processing if the key is invalid or CONTINUE processing if the key is valid. Should be simple enough, right? Let’s continue on and see!</p>
<hr />
<h2 id="heading-api-key-authentication-middleware-example-code"><strong>API Key Authentication Middleware Example Code</strong></h2>
<p>Now that you understand what middleware in ASP.NET core is, let’s look at an example. For my application, I wanted to handle the API key from the request header. Of course, this could be done in different ways, like having a query parameter for example, but the header was what I decided to go with.</p>
<p>Here’s the example API key authentication middleware in this code snippet:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">MyMiddleware</span>(<span class="hljs-params">
    HttpContext context,
    RequestDelegate next</span>)</span>
{
    <span class="hljs-comment">// if you wanted it as a query parameter, you'd</span>
    <span class="hljs-comment">// want to consider changing this part of the code!</span>
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> ApiKeyHeader = <span class="hljs-string">"&lt;YOUR_HEADER_KEY_HERE&gt;"</span>;
    <span class="hljs-keyword">if</span> (!context.Request.Headers.TryGetValue(ApiKeyHeader, <span class="hljs-keyword">out</span> <span class="hljs-keyword">var</span> apiKeyVal))
    {
        context.Response.StatusCode = <span class="hljs-number">401</span>;
        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Api Key not found."</span>);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> TheRealApiKey = <span class="hljs-string">"&lt;YOUR_SECRET_API_KEY_HERE&gt;"</span>;
    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.Equals(TheRealApiKey, apiKeyVal, StringComparison.Ordinal))
    {
        context.Response.StatusCode = <span class="hljs-number">401</span>;
        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Invalid API Key."</span>);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">await</span> next(context);
}
</code></pre>
<p>The code above is very much representative of <a target="_blank" href="https://www.devleader.ca/2024/01/05/chain-of-responsibility-pattern-in-c-simplified-how-to-guide/">the chain of responsibility design pattern</a>! Our middleware handler can take action, and then is able to call into the next delegate using the context that was passed in — or it can terminate the sequence by writing a response back and leaving the method without calling the next handler. But if you’re wondering where we hook this up, then check this code snippet:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// "app" here is the WebApplication instance after</span>
<span class="hljs-comment">// being built by the web application builder</span>
app.Use(MyMiddleware);
</code></pre>
<p>Odds are you do NOT want to have your API key right in your code — in fact, I would say “PLEASE DO NOT DO THIS!” so that you don’t accidentally commit a secret API key into your source control. A way that we can work around this is by using environment variables and the app configuration! So in the following code example, you can see a string value being looked up in the application’s configuration:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// "app" here is the WebApplication instance after</span>
<span class="hljs-comment">// being built by the web application builder</span>
<span class="hljs-keyword">var</span> config = app.Configuration
<span class="hljs-keyword">var</span> secretApiKey = config.GetValue&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-string">"&lt;CONFIG_KEY_NAME&gt;"</span>);
</code></pre>
<p>Now instead of comparing against a hard-coded API key directly in your code, you can read it from a configuration instance, which can be populated by environment variables!</p>
<hr />
<h2 id="heading-using-this-with-plugin-architecture-in-c"><strong>Using This With Plugin Architecture in C#</strong></h2>
<p>It’s no secret that <a target="_blank" href="https://www.devleader.ca/2024/03/12/plugin-architecture-in-c-for-improved-software-design/">I like using plugin architectures when I’m developing software</a> — but this might be your first time reading some of my content. So spoiler alert: I love using <a target="_blank" href="https://www.devleader.ca/2023/09/07/plugin-architecture-design-pattern-a-beginners-guide-to-modularity/">plugins when designing</a> software systems.</p>
<p>In the ASP.NET Core application that I wanted to add my API key authentication middleware to, I have a very simple loading scheme that allows dependencies to “hook” into the web application building process. This is accomplished by a couple of basic steps:</p>
<ul>
<li><p>I use Autofac and assembly scanning to look for DLLs with Autofac modules to load in at startup time</p>
</li>
<li><p>These DLLs become plugins, so by definition any plugin can then use the dependency container builder to register their own dependencies</p>
</li>
<li><p>Part of that registration process means they can ask the container for the web application instance that was built</p>
</li>
<li><p>Once they have that web application instance, they are able to hook up their middleware to it.</p>
</li>
</ul>
<p>This is a very simple/naive way to do this because there’s no ordering or control on the middleware. If certain middleware MUST be registered before/after other middleware, there’s no opportunity to say so — You just buckle up and hope for the best. However, that’s okay for now because my middleware needs are EXTREMELY limited currently. I will create an ordering scheme for this if/when necessary.</p>
<p>So what does my plugin code look like? Pretty much what we saw earlier, except <a target="_blank" href="https://www.devleader.ca/2023/10/02/how-to-organize-autofac-modules-5-tips-for-organizing-code/">inside of an Autofac module</a>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ApiKeyModule</span> : <span class="hljs-title">Module</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Load</span>(<span class="hljs-params">ContainerBuilder builder</span>)</span>
    {
        builder
            .Register(ctx =&gt;
            {
                <span class="hljs-keyword">var</span> app = ctx.Resolve&lt;WebApplication&gt;();
                <span class="hljs-keyword">var</span> config = ctx.Resolve&lt;IConfiguration&gt;();

                <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> ApiKeyConfigKey = <span class="hljs-string">"API_CONFIG_KEY_NAME"</span>;
                Lazy&lt;<span class="hljs-keyword">string</span>?&gt; lazyApiKey = <span class="hljs-keyword">new</span>(() =&gt; config.GetValue&lt;<span class="hljs-keyword">string</span>&gt;(ApiKeyConfigKey));

                app.Use(<span class="hljs-keyword">async</span> (context, next) =&gt;
                {
                    <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> ApiKeyHeader = <span class="hljs-string">"HEADER_KEY_NAME"</span>;
                    <span class="hljs-keyword">if</span> (!context.Request.Headers.TryGetValue(
                        ApiKeyHeader,
                        <span class="hljs-keyword">out</span> <span class="hljs-keyword">var</span> apiKeyVal))
                    {
                        context.Response.StatusCode = <span class="hljs-number">401</span>;
                        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Api Key not found."</span>);
                        <span class="hljs-keyword">return</span>;
                    }

                    <span class="hljs-keyword">var</span> apiKey = lazyApiKey.Value;
                    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.Equals(apiKey, apiKeyVal, StringComparison.Ordinal))
                    {
                        context.Response.StatusCode = <span class="hljs-number">401</span>;
                        <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Invalid API Key."</span>);
                        <span class="hljs-keyword">return</span>;
                    }

                    <span class="hljs-keyword">await</span> next(context);
                });

                <span class="hljs-comment">// this is used to help control the ordering of dependencies</span>
                <span class="hljs-comment">// so the application won't start until all of these</span>
                <span class="hljs-comment">// have been resolved!</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PostAppRegistrationDependencyMarker();
            })
            .SingleInstance();
    }
}
</code></pre>
<p>If you’re wondering what the benefit is: I never had to touch any other code in my project and I instantly added API authentication to every single route. This code <em>is</em> currently in the main assembly, but I could have added it to a new project, built the DLL, and dropped it into the running directory to get this behavior activated.</p>
<p>That’s the power of building with plugins!</p>
<hr />
<h2 id="heading-wrapping-up-api-key-authentication-middleware"><strong>Wrapping Up API Key Authentication Middleware</strong></h2>
<p>Overall, adding API key authentication middleware in ASP.NET Core applications is quite simple! The middleware can be added directly onto the application instance and you can decide how you’d like to load your secret API key to compare against. By sprinkling in a little bit of C# <a target="_blank" href="https://www.devleader.ca/2023/09/07/plugin-architecture-design-pattern-a-beginners-guide-to-modularity/">plugin architecture</a> like I prefer to use in many of my projects, it’s a breeze to extend the functionality of your ASP.NET Core app!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[8 Things I Wish I Understood Earlier In My Career]]></title><description><![CDATA[Our lives and careers are journeys, so we should expect that we’ll be learning for the duration we’re on this planet. As long as we’re moving forward in life, we have experiences to learn from. When I reflect on my career, there are a lot of lessons ...]]></description><link>https://hashnode.devleader.ca/8-things-i-wish-i-understood-earlier-in-my-career</link><guid isPermaLink="true">https://hashnode.devleader.ca/8-things-i-wish-i-understood-earlier-in-my-career</guid><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Career]]></category><category><![CDATA[Career Coach]]></category><category><![CDATA[career advice]]></category><category><![CDATA[learning]]></category><category><![CDATA[Learning Journey]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 22 Apr 2024 12:00:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1713182921136/d6d87fab-44ad-4934-9541-897027a2fa38.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Our lives and careers are journeys, so we should expect that we’ll be learning for the duration we’re on this planet. As long as we’re moving forward in life, we have experiences to learn from. When I reflect on my career, there are a lot of lessons that I wish I could have taught myself early on. While I can’t talk to my younger self, I can share these with you!</p>
<p>If you enjoy this kind of content, I often write about it in my weekly newsletter. You can subscribe to it for free:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-1-keep-building"><strong>1 – Keep Building</strong></h2>
<p>Keep building things. It doesn’t matter if they’re not million-dollar product ideas. Build things to learn about how they work.</p>
<p>The goal when we’re building things, especially early in our software engineering journeys, is not to get-rich-quick. The goal is to practice and learn.</p>
<p>There’s no shortcut to mastery except for understanding sooner that there’s no shortcut. We need to <a target="_blank" href="https://www.devleader.ca/2023/11/13/how-to-build-an-asp-net-core-web-api-a-practical-beginners-tutorial/">practice — so build</a> software.</p>
<h2 id="heading-2-reinvent-the-wheel"><strong>2 – Reinvent The Wheel</strong></h2>
<p>We’re always told to not reinvent the wheel. There’s no point doing it if someone else has already done it.</p>
<p>But this isn’t always good advice.</p>
<p>Reinventing the wheel is one of the best ways to <a target="_blank" href="https://www.devleader.ca/2023/12/29/how-to-understand-a-new-codebase-tips-and-tricks-for-tackling-complex-code/">understand how something works and the complexity</a> behind it. It might not be the best thing to chase in a production environment with paying customers, but it’s great for learning.</p>
<p>If you’re ever curious about how things work or interested in the complexities of a system or technology — try building it yourself. You’re almost guaranteed to learn something about what you’re diving into. I’d be shocked if you didn’t!</p>
<h2 id="heading-3-learn-in-public"><strong>3 – Learn In Public</strong></h2>
<p>Document your journey so others can learn alongside you. This can help reinforce learning in so many ways because you need to find ways to explain the concepts that you think you’re now understanding.</p>
<p>However, don’t masquerade as an expert. Be humble and acknowledge that you’re new and learning. Others will be more willing to help.</p>
<p>Remember that everyone has different opinions. Some people are more loud but it doesn’t make them more correct. In fact, the louder people unwilling to listen to other perspectives are more often than not going to be less helpful. So don’t be discouraged.</p>
<p>If people correct your mistakes, this is a great chance for you to take lessons learned and improve!</p>
<h2 id="heading-4-we-build-software-in-teams"><strong>4 – We Build Software In Teams</strong></h2>
<p>In the large majority of cases, software is built in teams. This means that you need to focus on communication skills, collaboration skills, and ALL of the other skills that aren’t just technical.</p>
<p>When it comes to technical direction, you need to consider that it’s not just your choices.</p>
<p>This is a good thing — because the different backgrounds, experiences, and perspectives will allow you to build better software as a group.</p>
<h2 id="heading-5-composition-gt-inheritance"><strong>5 – Composition &gt; Inheritance</strong></h2>
<p>Inheritance gets pushed a LOT when teaching programming but if you gravitate towards using composition early then you’ll “shortcut” a few years of really crappy code.</p>
<p>Seriously. I’m guilty of writing mountains of code with ridiculously long inheritance hierarchies. I can’t blame this entirely on WinForms and the Controls paradigm that was used… I should have taken some responsibility!</p>
<p>I’d spend a good portion of my early career rewriting a lot of overly complex inheritance code because it became too complex.</p>
<h2 id="heading-6-dont-fear-learning"><strong>6 – Don’t Fear Learning</strong></h2>
<p>Don’t be afraid to learn new things. Building expertise can feel great, but don’t let it make you feel so safe that new things feel scary.</p>
<p>You’re going to suck at new things but it’s very temporary. You’ll prove to yourself repeatedly that you eventually get working knowledge and feel very comfortable.</p>
<p>In my career, my best growth opportunities were when I was forced into something new and uncomfortable. Every time I came out on top.</p>
<p>Discomfort led to incredible learning experiences.</p>
<h2 id="heading-7-own-your-career-development"><strong>7 – Own Your Career Development</strong></h2>
<p>Nobody is as interested in your <a target="_blank" href="https://www.devleader.ca/2024/01/06/take-control-of-career-progression-dev-leader-weekly-25/">career progression</a> as you are. Great managers will indeed help encourage you and give you opportunities to move things along.</p>
<p>But we can’t just sit back and wait for this. We won’t always have amazing managers.</p>
<p>The sooner you realize that being passive is not a good strategy for progression, the sooner you can take action.</p>
<h2 id="heading-8-remember-to-have-fun"><strong>8 – Remember To Have Fun</strong></h2>
<p>You’re in this for the long haul, spending many hours of your life building software. You better enjoy it.</p>
<p>Not every day is going to be easy. Not every day will be interesting. Not every day will exciting.</p>
<p>But overall, you need to find ways to enjoy what you’re doing. It will help you learn. It will help you be engaged. It will help you be motivated to push through interesting challenges.</p>
<p>Software engineering is very mentally demanding and it’s often hard to find a good work-life balance… So keep this one in mind throughout your career.</p>
<hr />
<p>What would you add or change? If you found this insightful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[C# Regular Expression Benchmarks – How To Avoid My Mistakes!]]></title><description><![CDATA[Recently I published an article about the various performance characteristics of using regex in C#. Specifically, there are a handful of ways that we can use regular expressions in C# to do seemingly the same thing. I was curious about the difference...]]></description><link>https://hashnode.devleader.ca/csharp-regular-expression-benchmarks-how-to-avoid-my-mistakes</link><guid isPermaLink="true">https://hashnode.devleader.ca/csharp-regular-expression-benchmarks-how-to-avoid-my-mistakes</guid><category><![CDATA[C#]]></category><category><![CDATA[performance]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Regular Expressions]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Tue, 16 Apr 2024 12:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1713150204681/444bbe63-2a23-4bbc-92df-0a8187212fd2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently <a target="_blank" href="https://www.devleader.ca/2024/04/08/csharp-regex-performance-how-to-squeeze-out-performance/">I published an article about the various performance characteristics of using regex in C#</a>. Specifically, there are a handful of ways that we can use regular expressions in C# to do seemingly the same thing. I was curious about the differences, so I set out to collect some C# regular expression benchmarks… but I goofed.</p>
<p>In this article, I’ll explain my error so you can try to avoid this for yourself… and of course, I’ll provide new benchmarks and an update to the benchmarking code using BenchmarkDotNet.</p>
<hr />
<h2 id="heading-the-invalid-c-regular-expression-benchmarks"><strong>The Invalid C# Regular Expression Benchmarks</strong></h2>
<p>In <a target="_blank" href="https://www.devleader.ca/2024/04/08/csharp-regex-performance-how-to-squeeze-out-performance/">the previous article I wrote about C# regular expression benchmarks, I had results that illustrated</a> enormous performance gains if you were incorrectly using some of the available C# regex methods. The benchmark results clearly indicated that the cost of creating a new regex object in C# was expensive, and even more expensive if you had the compile flag. So if you were doing this each time you wanted to match, you were paying an unfortunately high penalty.</p>
<p>You can <a target="_blank" href="https://youtu.be/nw8B_E5ICMM">watch the video walking through these benchmarks here</a> to get a better idea, keeping in mind that the results we’re about to discuss are the correct ones:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/nw8B_E5ICMM">https://youtu.be/nw8B_E5ICMM</a></div>
<p> </p>
<p>There was a great YouTube comment that came up pretty shortly after the video was released, and here’s what the viewer had to say:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/youtube-comment-regex-performance-1024x306.webp" alt="C# Regular Expression Performance - YouTube Comment" /></p>
<p>That meant I had to go back to the drawing board to investigate!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-being-lazy-like-c-iterators"><strong>Being Lazy Like C# Iterators…</strong></h2>
<p>As the viewer pointed out… it looks like <code>MatchCollection</code> that comes back from doing a regex match is lazily evaluated. That might be confusing if you haven’t heard of this concept before, but <a target="_blank" href="https://www.devleader.ca/2023/12/23/love-hate-relationship-with-ienumerable-and-iterators-dev-leader-weekly-23/">this is all much like using iterators in C#</a>, which I have talked about extensively. If you want a bit of a crash course on the idea behind iterators in C#, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=qYoZn4Td41E">this video for a walkthrough of my experiences</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=qYoZn4Td41E">https://www.youtube.com/watch?v=qYoZn4Td41E</a></div>
<p> </p>
<p>Long story short: It looks like a line of code executes a method, but you’re simply just assigning a function pointer to a variable. The result is that instead of a method taking some amount of time to run, you instead have it execute nearly instantaneously.</p>
<p>But is the <code>MatchCollection</code> <em>actually</em> a C# iterator, or is it something else?</p>
<h3 id="heading-revisiting-the-c-regex-benchmark-code"><strong>Revisiting The C# Regex Benchmark Code</strong></h3>
<p>Let’s consider the following code, which is one of the simple benchmarks from the previous article:</p>
<pre><code class="lang-csharp">Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!, RegexOptions.Compiled);
<span class="hljs-keyword">return</span> regex.Matches(_sourceText!);
</code></pre>
<p>What we’re returning in that benchmark method is actually what’s called a <code>MatchCollection</code>. We could instead write that code as follows:</p>
<pre><code class="lang-csharp">Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!, RegexOptions.Compiled);
MatchCollection matches = regex.Matches(_sourceText!);
<span class="hljs-keyword">return</span> matches;
</code></pre>
<p>The line in the middle of the code example directly above looks like it’s evaluating all of the matches, but indeed it returns nearly instantly. That’s definitely not what we wanted to measure! Instead, I was just measuring the cost of creating a <code>MatchCollection</code> instance vs creating an entire C# Regex object instance plus a <code>MatchCollection</code> instance. This explains why of course the two benchmarks that created instances were absolutely guaranteed to be slower — they did the same thing when it came to creating a <code>MatchCollection</code> instance, but they had their own associated overhead for regular expression creation.</p>
<h3 id="heading-whats-happening-with-matchcollection"><strong>What’s Happening With MatchCollection?</strong></h3>
<p>Well, it turns out that <code>MatchCollection</code> is not quite an iterator, but it certainly is lazily evaluated. If you keep jumping to the definition and go deeper into the code for <code>MatchCollection</code>, you’ll see the following:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">EnsureInitialized</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">if</span> (!_done)
    {
        GetMatch(<span class="hljs-keyword">int</span>.MaxValue);
    }
}
</code></pre>
<p>This is a method called in many spots within the <code>MatchCollection</code> class, and basically any time someone wants to access information about the matches, we eventually need to get into the <code>GetMatch</code> method. That method looks as follows:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">private</span> Match? GetMatch(<span class="hljs-keyword">int</span> i)
{
    Debug.Assert(i &gt;= <span class="hljs-number">0</span>, <span class="hljs-string">"i cannot be negative."</span>);

    <span class="hljs-keyword">if</span> (_matches.Count &gt; i)
    {
        <span class="hljs-keyword">return</span> _matches[i];
    }

    <span class="hljs-keyword">if</span> (_done)
    {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }

    Match match;
    <span class="hljs-keyword">do</span>
    {
        match = _regex.RunSingleMatch(
            RegexRunnerMode.FullMatchRequired,
            _prevlen,
            _input,
            <span class="hljs-number">0</span>,
            _input.Length,
            _startat)!;
        <span class="hljs-keyword">if</span> (!match.Success)
        {
            _done = <span class="hljs-literal">true</span>;
            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
        }

        _matches.Add(match);
        _prevlen = match.Length;
        _startat = match._textpos;
    } <span class="hljs-keyword">while</span> (_matches.Count &lt;= i);

    <span class="hljs-keyword">return</span> match;
}
</code></pre>
<p>If you step through this code, you’ll notice that there’s state kept for how far along in the matches a caller is looking for. That means if this instance has not yet been evaluated that far along, it will then go attempt to evaluate that far based on the requested index. Looks pretty lazy to me! But if that wasn’t a giveaway… Look how the constructor doesn’t even take a collection of matches at the time of creation!</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">internal</span> <span class="hljs-title">MatchCollection</span>(<span class="hljs-params">Regex regex, <span class="hljs-keyword">string</span> input, <span class="hljs-keyword">int</span> startat</span>)</span>
{
    <span class="hljs-keyword">if</span> ((<span class="hljs-keyword">uint</span>)startat &gt; (<span class="hljs-keyword">uint</span>)input.Length)
    {
        ThrowHelper.ThrowArgumentOutOfRangeException(
            ExceptionArgument.startat,
            ExceptionResource.BeginIndexNotNegative);
    }

    _regex = regex;
    _input = input;
    _startat = startat;
    _prevlen = <span class="hljs-number">-1</span>;
    _matches = <span class="hljs-keyword">new</span> List&lt;Match&gt;();
    _done = <span class="hljs-literal">false</span>;
}
</code></pre>
<p>Please keep in mind that this is what Visual Studio is showing me, and if you try checking the source at a later point it may be different in the dotnet code.</p>
<p>You can also <a target="_blank" href="https://www.youtube.com/watch?v=B14MzCqPFUY">follow along with this video here</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=B14MzCqPFUY">https://www.youtube.com/watch?v=B14MzCqPFUY</a></div>
<p> </p>
<hr />
<h2 id="heading-the-new-code-for-c-regulhttpswwwyoutubecomwatchvb14mzcqpfuyar-expression-benchmarks"><a target="_blank" href="https://www.youtube.com/watch?v=B14MzCqPFUY"><strong>The New Code for C# Regul</strong></a><strong>ar Expression Benchmarks</strong></h2>
<p>Let’s jump right into the new BenchmarkDotNet code for these regular expression scenarios, which will look VERY similar to before:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> BenchmarkDotNet.Attributes;
<span class="hljs-keyword">using</span> BenchmarkDotNet.Running;

<span class="hljs-keyword">using</span> System.Reflection;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

BenchmarkRunner.Run(
    Assembly.GetExecutingAssembly(), 
    args: args);

[<span class="hljs-meta">MemoryDiagnoser</span>]
[<span class="hljs-meta">MediumRunJob</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RegexBenchmarks</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> RegexPattern = <span class="hljs-string">@"\b\w*(ing|ed)\b"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _sourceText;
    <span class="hljs-keyword">private</span> Regex? _regex;
    <span class="hljs-keyword">private</span> Regex? _regexCompiled;
    <span class="hljs-keyword">private</span> Regex? _generatedRegex;
    <span class="hljs-keyword">private</span> Regex? _generatedRegexCompiled;

    [<span class="hljs-meta">GeneratedRegex(RegexPattern, RegexOptions.None, <span class="hljs-meta-string">"en-US"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">partial</span> Regex <span class="hljs-title">GetGeneratedRegex</span>(<span class="hljs-params"></span>)</span>;

    [<span class="hljs-meta">GeneratedRegex(RegexPattern, RegexOptions.Compiled, <span class="hljs-meta-string">"en-US"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">partial</span> Regex <span class="hljs-title">GetGeneratedRegexCompiled</span>(<span class="hljs-params"></span>)</span>;

    [<span class="hljs-meta">Params(<span class="hljs-meta-string">"pg73346.txt"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? SourceFileName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">GlobalSetup</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Setup</span>(<span class="hljs-params"></span>)</span>
    {
        _sourceText = File.ReadAllText(SourceFileName!);

        _regex = <span class="hljs-keyword">new</span>(RegexPattern);
        _regexCompiled = <span class="hljs-keyword">new</span>(RegexPattern, RegexOptions.Compiled);
        _generatedRegex = GetGeneratedRegex();
        _generatedRegexCompiled = GetGeneratedRegexCompiled();
    }

    [<span class="hljs-meta">Benchmark(Baseline = true)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Static</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> Regex.Matches(_sourceText!, RegexPattern!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">New</span>(<span class="hljs-params"></span>)</span>
    {
        Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!);
        <span class="hljs-keyword">return</span> regex.Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">New_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!, RegexOptions.Compiled);
        <span class="hljs-keyword">return</span> regex.Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Cached</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _regex!.Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Cached_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _regexCompiled!.Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Generated</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> GetGeneratedRegex().Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Generated_Cached</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _generatedRegex!.Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Generated_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> GetGeneratedRegexCompiled().Matches(_sourceText!).Count;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">Generated_Cached_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _generatedRegexCompiled!.Matches(_sourceText!).Count;
    }
}
</code></pre>
<p>If you <a target="_blank" href="https://www.devleader.ca/2024/04/08/csharp-regex-performance-how-to-squeeze-out-performance/">compare these benchmark methods to the previous article</a>, you’ll notice they are very close with a very subtle difference: I’m returning an integer count instead of the <code>MatchCollection</code>. If you consider this and what I pointed out in the code earlier, <code>Count</code> is one of the properties on <code>MatchCollection</code> that will eventually try to evaluate the matches under the hood — as in, it will force the lazy behavior to get evaluated.</p>
<p>We can see that by factoring in this code snippet below:</p>
<pre><code class="lang-csharp"><span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;summary&gt;</span></span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> Returns the number of captures.</span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> <span class="hljs-doctag">&lt;/summary&gt;</span></span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Count
{
    <span class="hljs-keyword">get</span>
    {
        EnsureInitialized();
        <span class="hljs-keyword">return</span> _matches.Count;
    }
}
</code></pre>
<hr />
<h2 id="heading-the-new-results-of-c-regular-expression-benchmarks"><strong>The New Results of C# Regular Expression Benchmarks</strong></h2>
<p>Now that I’ve come clean and admitted that I totally screwed up on my benchmarks AND provided you the updated code, let’s redo this analysis. Here are the newly run benchmarks:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/regex-performance-corrected-1024x390.webp" alt="C# Regular Expression Benchmarks - Corrected Results" /></p>
<p>Now here are some interesting things to make note of:</p>
<ul>
<li><p>The static method call is indeed the worst of all the options. While it’s nearly identical, creating a new regex is only a tiny bit faster as these benchmark results show. Under the hood, the static method call does try to get or add the regex to a cache, which seems to be a static collection of regular expressions that have been created. <em>MORE ON THIS SHORTLY</em></p>
</li>
<li><p>It looks like now in these benchmarks the overhead of compiling the regex is now WORTH doing, even if you’re going to do it each time you go to find matches. About a 56% performance boost! We need to keep in mind the pattern I’m using, the contents of data that’s being tested, and the overall length of that data as well.</p>
</li>
<li><p>Simply caching the regex in a field shows very minimal performance benefits, if not just a rounding error, for this setup. Again, this could be largely due to the size of the data and the pattern being used, and perhaps a very short set of data to scan would make caching proportionally more advantageous.</p>
</li>
<li><p>Now we get into the magic territory where we can see caching a compiled regex gives us performance that is 310% of the baseline. Not having to recompile is very helpful here!</p>
</li>
<li><p>As predicted, like in the original article, all of the generated regexes are on par with each other, and in this test setup perform exactly on par with the compiled cached regex.</p>
</li>
</ul>
<h2 id="heading-but-wait-theres-caching"><strong>But Wait! There’s Caching!</strong></h2>
<p>I wanted to be even more careful before publishing this follow-up article on C# regular expression benchmarks because of the first slip up I had. I recalled that the regex class has a <code>RegexCache</code> internal to the dotnet code that is running — and since we’re using the same pattern over and over… Are we caching things behind the scenes?</p>
<p>It turns out, we can change the cache size to zero by doing the following:</p>
<pre><code class="lang-csharp">Regex.CacheSize = <span class="hljs-number">0</span>;
</code></pre>
<p>If I add this line of code to the beginning of the benchmark runner, I can be assured that the caching is turned off. But just to be sure, I added this <a target="_blank" href="https://youtu.be/_v9k74gWJtE">debug watch in Visual Studio</a> after creating a regex just to sanity check:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">typeof</span>(RegexCache)
    .GetField(<span class="hljs-string">"s_cacheList"</span>, BindingFlags.Static | BindingFlags.NonPublic)
    .GetValue(<span class="hljs-literal">null</span>)
</code></pre>
<p>The result of this was seeing an empty cache, which is exactly what I was hoping for. A quick note is that <code>RegexCache</code> is internal, and I wasn’t sure the best way to get reflection to work in code to access this (i.e. not sure which assembly to go look at), but this does resolve properly in the debug watch list! But now you’re probably interested in the results:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/regex-performance-corrected-no-cache-1024x401.webp" alt="C# Regular Expression Benchmarks - Corrected Results No Cache" /></p>
<p>Interestingly — there’s really no difference here. I suspect this is largely because the text we’re scanning through is large enough that the time it takes to evaluate regex matches mostly dwarfs the time it takes to create the regex objects. This is exactly what was <em>not</em> shown in the original article where the time to evaluate was basically zero because we never evaluated the matches.</p>
<hr />
<h2 id="heading-wrapping-up-c-regular-expression-benchmarks"><strong>Wrapping Up C# Regular Expression Benchmarks</strong></h2>
<p>Okay, now it’s time for some lessons learned…</p>
<ol>
<li><p>It’s okay to make mistakes. We’re all human.</p>
</li>
<li><p>Mistakes are a great way to take ownership and show others that we can grow from messing up!</p>
</li>
<li><p>Failing is one of the best ways to learn. I had absolutely no idea <code>MatchCollection</code> was lazy after probably 10+ years of using Regex in C#.</p>
</li>
</ol>
<p>At the end of the day, these new C# regular expression benchmarks are still very helpful in understanding just how big of an impact compiling your regex can have! Ideally, you don’t want to be recreating new regex instances, especially with the compile flag… but the performance of compiled regexes is awesome.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[C# Regex Performance: How To Squeeze Out Performance]]></title><description><![CDATA[Regular expressions in C# can save you when you need to do some complex pattern matching on strings. But as the language grows and evolves we continue to get new ways that we can use regular expressions in C#. That’s why I wanted to take a moment to ...]]></description><link>https://hashnode.devleader.ca/csharp-regex-performance-how-to-squeeze-out-performance</link><guid isPermaLink="true">https://hashnode.devleader.ca/csharp-regex-performance-how-to-squeeze-out-performance</guid><category><![CDATA[C#]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[performance]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 15 Apr 2024 12:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1712578119529/a9a57e35-34af-4db6-b43c-2a29c6501ebd.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Regular expressions in C# can save you when you need to do some complex pattern matching on strings. But as the language grows and evolves we continue to get new ways that we can use regular expressions in C#. That’s why I wanted to take a moment to consider C# Regex performance by running benchmarks across the various ways I’m familiar with using regular expressions.</p>
<p>When we have options that look the same, I like remaining curious and understanding what’s <em>actually</em> different. This turned out to be a fun exercise and I hope you have some learnings to take away just like I did!</p>
<h2 id="heading-please-note"><strong>PLEASE NOTE:</strong></h2>
<p>There was an error in the benchmarks that I created because of an assumption that was invalid. The contents of this article can still be very valuable, but there is an update to the benchmark code and an accurate analysis in this follow-up article:<br /><a target="_blank" href="https://www.devleader.ca/2024/04/12/csharp-regular-expression-benchmarks-how-to-avoid-my-mistakes/">https://www.devleader.ca/2024/04/12/csharp-regular-expression-benchmarks-how-to-avoid-my-mistakes/</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-what-is-a-regular-expression"><strong>What is a Regular Expression?</strong></h2>
<p>Regular expressions, often referred to as regex, are powerful tools used for pattern matching in text. They allow you to define a search pattern that can be used to find, replace, or manipulate specific parts of a string. Regular expressions provide a concise and flexible way to search for and identify specific patterns within text data.</p>
<p>I have used regular expressions for many different things in my career such as:</p>
<ul>
<li><p>Pattern matching on user input</p>
</li>
<li><p>Scraping data from the web</p>
</li>
<li><p>Parsing data sources like logs or other files</p>
</li>
<li><p>Digital forensics data recovery</p>
</li>
<li><p>… and many more uses!</p>
</li>
</ul>
<p>Regular expressions can be used for all sorts of advanced pattern matching. But if you want to get started you can check out these articles:</p>
<ul>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/04/02/regular-expressions-in-csharp-3-examples-you-need-to-know/">Some simple examples using C# regular expressions</a></p>
</li>
<li><p><a target="_blank" href="https://www.devleader.ca/2024/04/01/regex-options-in-csharp-beginners-guide-to-powerful-pattern-matching/">C# Regex options</a></p>
</li>
</ul>
<hr />
<h2 id="heading-why-benchmark-regex-performance-in-c"><strong>Why Benchmark Regex Performance in C#?</strong></h2>
<p>Aside from when I am trying to profile and optimize my applications and services, I like benchmarking things when I am curious. This happens especially when I find there are seemingly multiple ways to do the same thing — it makes me wonder TRULY what the differences are aside form just syntax and usability. Recently <a target="_blank" href="https://www.devleader.ca/2024/03/31/collection-initializer-performance-in-c-double-your-performance-with-what/">with collection initializers, I was completely blown away by the performance differences</a>, so it’s always a good reminder to be curious.</p>
<p>Regular expressions in C# have several different flavors:</p>
<ul>
<li><p>Static method call</p>
</li>
<li><p>Compiled flag or not</p>
</li>
<li><p>Source generators</p>
</li>
</ul>
<p>Now, the compiled flag is supposed to give us a performance boost but what’s the overhead of using just the static method call since it makes things really convenient to call in code? And what the heck are these (relatively) new source generators for regular expressions in C#? Microsoft had some REALLY awesome <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-source-generators">documentation on compiled regular expressions and source generation</a> — and I never would have stumbled upon this if I wasn’t curious to benchmark.</p>
<p>While we won’t be comparing all of the regex methods we have access to, I did want to see the performance difference for getting all matches in a body of text. Considering the scenarios listed above, I was curious to see which would pull forward given they all seem roughly the same on the surface.</p>
<hr />
<h2 id="heading-setting-up-c-regex-performance-benchmarks"><strong>Setting Up C# Regex Performance Benchmarks</strong></h2>
<p>I know you’re eager to jump STRAIGHT to the details, and while nothing is stopping you from scrolling to the bottom I’m hopeful you’ll pause in this section to understand the benchmarks first. When I post benchmarking investigations, my ultimate goal is not to persuade you to code differently, but rather to be curious about what you’re coding. I think we’ll see some obvious things to avoid in these benchmarks — but still, being curious is the goal.</p>
<p>I’ll be working with BenchmarkDotNet as usual for these benchmarks. If you’re interested in learning more about how to run your own benchmarks I have plenty of <a target="_blank" href="https://www.devleader.ca/2024/03/05/how-to-use-benchmarkdotnet-simple-performance-boosting-tips-to-get-started/">BenchmarkDotNet articles you can check out</a>.</p>
<h3 id="heading-the-test-data-for-benchmarking"><strong>The Test Data For Benchmarking</strong></h3>
<p>While we’re not interested in absolute performance here — and you might be if you’re profiling and benchmarking your own application — we are interested in relative performance between our various Regex options. Aside from the options we have to use, some other considerations:</p>
<ul>
<li><p>The Regex pattern that we use could potentially influence how each mechanism performs</p>
</li>
<li><p>The source of data we try to match could have some sort of influence on the results</p>
</li>
</ul>
<p>I call these things out because they are uncertain to me. The source data I feel shouldn’t be TOO big of an issue — but maybe different heuristics of matching don’t allow compiled or source-generated regular expressions to shine. Maybe the Regex pattern I’ve selected doesn’t allow compiled or source-generated regular expressions to have an advantage. Or maybe it does — and I should be able to call this out.</p>
<p>The point is that there are some variables that may influence results and I don’t fully understand how. But this is me being transparent, and if you know better feel free to share your insights!</p>
<p>I figured to make this as “fair” as possible, I would look for some patterns in real text: words that end in “ing” or in “ed”. To find some real text, I am using the <a target="_blank" href="https://www.gutenberg.org/ebooks/73346">data from Project Gutenberg — Specifically, this E-Book</a>. It’s 2200+ lines of English text so there are plenty of matches on words for our pattern.</p>
<h3 id="heading-the-c-regex-benchmark-code"><strong>The C# Regex Benchmark Code</strong></h3>
<p>There’s nothing super unique about these benchmarks compared to others I normally create. However, I’ll list out some points of interest so that you can pick them out in the code:</p>
<ul>
<li><p>I’m using [Params] to load the source file in case you want to try these benchmarks across different datasets</p>
</li>
<li><p>The source data is read in during the global setup</p>
</li>
<li><p>I need to cache some Regex instances for some of the benchmarks, which is done in the global setup</p>
</li>
</ul>
<p>You can <a target="_blank" href="https://github.com/ncosentino/DevLeader/tree/master/WorkingWithRegex/WorkingWithRegex.RegexBenchmarks">find the benchmark code here on GitHub</a> and in the code below:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> BenchmarkDotNet.Attributes;
<span class="hljs-keyword">using</span> BenchmarkDotNet.Running;

<span class="hljs-keyword">using</span> System.Reflection;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

BenchmarkRunner.Run(
    Assembly.GetExecutingAssembly(), 
    args: args);

[<span class="hljs-meta">MemoryDiagnoser</span>]
[<span class="hljs-meta">MediumRunJob</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">partial</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RegexBenchmarks</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> RegexPattern = <span class="hljs-string">@"\b\w*(ing|ed)\b"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? _sourceText;
    <span class="hljs-keyword">private</span> Regex? _regex;
    <span class="hljs-keyword">private</span> Regex? _regexCompiled;
    <span class="hljs-keyword">private</span> Regex? _generatedRegex;
    <span class="hljs-keyword">private</span> Regex? _generatedRegexCompiled;

    [<span class="hljs-meta">GeneratedRegex(RegexPattern, RegexOptions.None, <span class="hljs-meta-string">"en-US"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">partial</span> Regex <span class="hljs-title">GetGeneratedRegex</span>(<span class="hljs-params"></span>)</span>;

    [<span class="hljs-meta">GeneratedRegex(RegexPattern, RegexOptions.Compiled, <span class="hljs-meta-string">"en-US"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">partial</span> Regex <span class="hljs-title">GetGeneratedRegexCompiled</span>(<span class="hljs-params"></span>)</span>;

    [<span class="hljs-meta">Params(<span class="hljs-meta-string">"pg73346.txt"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span>? SourceFileName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">GlobalSetup</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Setup</span>(<span class="hljs-params"></span>)</span>
    {
        _sourceText = File.ReadAllText(SourceFileName!);

        _regex = <span class="hljs-keyword">new</span>(RegexPattern);
        _regexCompiled = <span class="hljs-keyword">new</span>(RegexPattern, RegexOptions.Compiled);
        _generatedRegex = GetGeneratedRegex();
        _generatedRegexCompiled = GetGeneratedRegexCompiled();
    }

    [<span class="hljs-meta">Benchmark(Baseline = true)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Static</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> Regex.Matches(_sourceText!, RegexPattern!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">New</span>(<span class="hljs-params"></span>)</span>
    {
        Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!);
        <span class="hljs-keyword">return</span> regex.Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">New_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        Regex regex = <span class="hljs-keyword">new</span>(RegexPattern!, RegexOptions.Compiled);
        <span class="hljs-keyword">return</span> regex.Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Cached</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _regex!.Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Cached_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _regexCompiled!.Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Generated</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> GetGeneratedRegex().Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Generated_Cached</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _generatedRegex!.Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Generated_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> GetGeneratedRegexCompiled().Matches(_sourceText!);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> MatchCollection <span class="hljs-title">Generated_Cached_Compiled</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> _generatedRegexCompiled!.Matches(_sourceText!);
    }
}
</code></pre>
<p>For our benchmarks, we’ll treat the static method on the Regex class as the baseline — just so we have something to anchor to when looking at the performance results.</p>
<hr />
<h2 id="heading-c-regex-performance-results"><strong>C# Regex Performance Results</strong></h2>
<p>With the BenchmarkDotNet code out of the way, let’s see the results:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/04/regex-performance-1024x352.webp" alt="C# Regex Performance Results" /></p>
<p>From above we can see that creating a new Regex instance every time you want to perform a match is 100x slower than the static method. This is incredible — you should NOT do this if performance is important to you! But it gets worse… If you do this AND provide the compile flag, it’s almost 1000x as bad, 10x worse than newing it up every time. These are two things you should avoid doing.</p>
<p>We can see with the cached variations that follow that we can effectively invert the situation, giving us a slight boost over the static method. While these runtimes are very fast, it looks like in these situations it’s nearly 30% faster. But temper your expectations as I’m not convinced this scales with different data sets and different patterns!</p>
<p>The source-generated C# regular expressions are also much faster than the static method — but seem roughly on par with the two prior benchmarks. While the source-generated regular expressions do cache and calling the source-generated method should be no overhead, there are two benchmark variations that suggest it’s marginally faster to keep your own cache. These could simply be outliers though given how close the results are.</p>
<p>You can check out <a target="_blank" href="https://youtu.be/nw8B_E5ICMM">the video for a full walk-through on these C# regex benchmarks</a>:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/nw8B_E5ICMM">https://youtu.be/nw8B_E5ICMM</a></div>
<p> </p>
<hr />
<h2 id="heading-wrapping-up-c-regex-performance"><strong>Wrapping Up C# Regex Performance</strong></h2>
<p>The takeaways for optimizing C# Regex performance: Stop declaring regular expressions in C# right before you go to use them! And even worse, stop declaring them with the compiled flag if you’re declaring them right before using them! These two things will crush your performance.</p>
<p>Otherwise, it seems like the Regex class with static method across the board is pretty safe, but you get the most benefit out of compiling and caching your regex. And according to Microsoft, can be improved even further with the C# Regex source generators in many situations.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Examples of Composition in C# – A Simple Guide for Beginners]]></title><description><![CDATA[In software engineering, composition plays an important role in object-oriented programming. If you’ve come across other articles or videos I’ve put out about object-oriented programming, you’ll know that I try to push composition over inheritance as...]]></description><link>https://hashnode.devleader.ca/examples-of-composition-in-csharp-a-simple-guide-for-beginners</link><guid isPermaLink="true">https://hashnode.devleader.ca/examples-of-composition-in-csharp-a-simple-guide-for-beginners</guid><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[software development]]></category><category><![CDATA[C#]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Fri, 12 Apr 2024 12:00:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1712232519026/655da6fa-bce3-4ebc-9c19-8e9fb05d575d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In software engineering, composition plays an important role in object-oriented programming. If you’ve come across other articles or videos I’ve put out about object-oriented programming, you’ll know that I try to push composition over inheritance as much as I can. This is strictly because I have seen overuse of inheritance throughout my entire career but I’ve never seen overuse of composition! But in this article, I’ll be walking you through examples of composition in C# so you can see what it means to see objects modeled with an “is made up of” relationship.</p>
<hr />
<h2 id="heading-what-is-composition-in-object-oriented-programming"><strong>What is Composition in Object-Oriented Programming?</strong></h2>
<p>In object-oriented programming, composition refers to the concept of building complex functionality by combining smaller objects together. When we talk about composition, we mean that objects can be composed of other objects, known as “components” or “parts”, to achieve a desired behavior or functionality. I like saying that composition represents an “is made up of” relationship, whereas when we talk about inheritance we mean that things have an “is a” relationship.</p>
<p>Let’s see if we can get this idea to be a little bit more clear with an example. We’ll stick to something that isn’t C# specific or even code-related so that you can rationalize the concept of an “is made up of” relationship.</p>
<p>Let’s consider a music band as a combination of musicians:</p>
<ul>
<li><p>a guitarist</p>
</li>
<li><p>a drummer</p>
</li>
<li><p>a singer</p>
</li>
</ul>
<p>Each member plays their own instrument or role and there is no relationship between each of these members aside from being in the same band. When we describe the band itself, we would say the band “has-a” guitarist, “has-a” drummer, and “has-a” singer. We could also then say that the band “is made up of” these musicians!</p>
<p>This illustrates composition, where we assemble different elements (musicians) each with unique capabilities, to create a complete unit (the band) that performs music together. Each member contributes their part to the overall performance, showcasing how individual components are combined to achieve a larger, coordinated function. I might even slip in another example here where we say the complexity of the musicians working together is “encapsulated” when are on the outside of the band, listening to the music.</p>
<hr />
<h2 id="heading-how-composition-works-in-c"><strong>How Composition Works in C#</strong></h2>
<p>So, how does composition work in C#, and how can you leverage this technique in your software development? Hint: it doesn’t start with inheriting from a base class!</p>
<p>To create composition relationships between objects in C#, we can use classes and interfaces. A class represents a blueprint for creating objects, while an interface defines a contract that a class must follow. By using composition, we can bring together various classes and interfaces to form a cohesive and flexible system.</p>
<p>It’s also important to note that we can compose objects of other objects and NOT use interfaces at all, but I thought excluding the usage of interfaces entirely might be misleading. So you <em>can</em> use interfaces as the things you will compose other objects of, but you do not <em>need</em> to for it to be a composition relationship.</p>
<hr />
<h2 id="heading-examples-of-composition-in-c"><strong>Examples of Composition in C#</strong></h2>
<p>In object-oriented programming, composition is a powerful concept that allows us to model relationships between real-world entities. By leveraging composition, we can create complex systems by combining smaller, more manageable components. Let’s explore some examples of composition in different scenarios using C# code snippets.</p>
<h3 id="heading-music-player-composition-example-in-c"><strong>Music Player Composition Example in C#</strong></h3>
<p>Let’s see composition in action! Consider this simple example of a music player application. We might have a <code>MusicPlayer</code> class that represents the core functionality of the application, such as playing audio files. However, the music player also needs additional capabilities, such as a user interface and audio codecs. That is, we can’t have something that plays music without it being made of these two dependencies! Here’s some example code:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MusicPlayer</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IUserInterface _userInterface;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IAudioCodec _audioCodec;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MusicPlayer</span>(<span class="hljs-params">
        IUserInterface userInterface,
        IAudioCodec audioCodec</span>)</span>
    {
        _userInterface = userInterface;
        _audioCodec = audioCodec;
    }

    <span class="hljs-comment">// Do stuff using the user interface</span>
    <span class="hljs-comment">// and the audio codec</span>

    <span class="hljs-comment">// Rest of the implementation...</span>
}
</code></pre>
<p>In the example above, the <code>MusicPlayer</code> class depends on an <code>IUserInterface</code> and an <code>IAudioCodec</code> interface. Instead of implementing these dependencies directly in the <code>MusicPlayer</code> class, we use composition to inject them as constructor parameters. This allows us to easily swap out different implementations of the user interface and audio codecs, providing flexibility and extensibility to our music player application.</p>
<p>Now, let’s see how we can compose the music player with concrete implementations of the interfaces:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ConsoleUserInterface</span> : <span class="hljs-title">IUserInterface</span>
{
    <span class="hljs-comment">// Implementation of IUserInterface...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Mp3AudioCodec</span> : <span class="hljs-title">IAudioCodec</span>
{
    <span class="hljs-comment">// Implementation of IAudioCodec...</span>
}

<span class="hljs-comment">// Usage</span>
<span class="hljs-keyword">var</span> userInterface = <span class="hljs-keyword">new</span> ConsoleUserInterface();
<span class="hljs-keyword">var</span> audioCodec = <span class="hljs-keyword">new</span> Mp3AudioCodec();
<span class="hljs-keyword">var</span> musicPlayer = <span class="hljs-keyword">new</span> MusicPlayer(
    userInterface,
    audioCodec);
</code></pre>
<p>In this example, we have two classes, <code>ConsoleUserInterface</code> and <code>Mp3AudioCodec</code>, that implement the <code>IUserInterface</code> and <code>IAudioCodec</code> interfaces, respectively. We then create instances of these concrete classes and pass them into the <code>MusicPlayer</code> constructor to compose the music player object.</p>
<p>By using composition, we have decoupled the specific implementations from the <code>MusicPlayer</code> class, making it more flexible and maintainable. Furthermore, if we want to add new user interfaces or audio codecs in the future, we can simply create new classes that implement the respective interfaces and inject them into the <code>MusicPlayer</code> class, without needing to modify its code.</p>
<h3 id="heading-example-of-composition-between-a-car-and-its-engine"><strong>Example of Composition Between a Car and its Engine</strong></h3>
<p>I often fall back to this example when explaining composition — and in fact, <a target="_blank" href="https://www.devleader.ca/courses/">you’ll find something like this in my Dometrain courses</a>. In this composition scenario, a car contains an engine, but the car does not inherit from the engine class. Instead, the car class has a reference to an engine object, which it uses to perform actions such as starting the engine or accelerating. If you start to consider how many different parts go into the car — or even how many parts go into an engine — you can start to see how we can compose objects of other objects.</p>
<p>Let’s have a quick look at some simple code that shows how this is modeled:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Engine</span>
{
    <span class="hljs-comment">// Engine implementation</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Car</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> Engine _engine;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Car</span>(<span class="hljs-params">Engine engine</span>)</span>
    {
        _engine = engine;
    }

    <span class="hljs-comment">// Car methods and properties</span>
}
</code></pre>
<p>By using composition, we can easily swap out different types of engines without modifying the car class. This flexibility allows us to handle various engine configurations, such as gasoline or electric, without changing the car’s implementation.</p>
<p><a target="_blank" href="https://dometrain.com/bundle/from-zero-to-hero-csharp?affcode=1115529_nl-teyzg"><img src="https://www.devleader.ca/wp-content/uploads/2024/04/courses-dometrain-C-bundle.webp" alt="C# From Zero to Hero - Dometrain Course" class="image--center mx-auto" /></a></p>
<h3 id="heading-composition-example-of-a-house-and-its-rooms"><strong>Composition Example of a House and its Rooms</strong></h3>
<p>A house is composed of multiple rooms, each serving a different purpose. Composition can be used to represent this relationship in an object-oriented manner.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> interfac IRoom
{
    <span class="hljs-comment">// Room properties and methods</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">House</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IReadOnlyList&lt;IRoom&gt; _rooms;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">House</span>(<span class="hljs-params">List&lt;Room&gt; rooms</span>)</span>
    {
        _rooms = rooms;
    }

    <span class="hljs-comment">// House methods and properties</span>
}
</code></pre>
<p>By using composition, we can easily create a house of different rooms. The way that this particular <code>House</code> type is set up, we can pass in a collection of <code>IRoom</code> instances and we’ll track them in a field. But because we’re using an <code>IRoom</code> interface, this could allow us to create a house with multiple rooms where we don’t care about the implementation of the room! So if you wanted your dream house to be 50 kitchens, you could absolutely create a <code>Kitchen</code> type that inherits from IRoom and pass in 50 instances of them when you create your house!</p>
<h3 id="heading-multiple-levels-of-composition-in-c"><strong>Multiple Levels of Composition in C#</strong></h3>
<p>To conclude the code examples, let’s go one level deeper. We’ve seen several examples of having one object being composed of one or more other objects, but what if we wanted to illustrate the extension of this?</p>
<p>In this code example, we’ll look at a library:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// public getters and setters just for</span>
<span class="hljs-comment">// ease-of-use when showing this example</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Library</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">List</span>&lt;<span class="hljs-title">BookShelf</span>&gt; BookShelves</span> { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">new</span> List&lt;BookShelf&gt;();
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BookShelf</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Number { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">List</span>&lt;<span class="hljs-title">Book</span>&gt; Books</span> { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-keyword">new</span> List&lt;Book&gt;();
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Book</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Title { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Author { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> YearPublished { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-comment">// Example Usage</span>
<span class="hljs-keyword">var</span> myLibrary = <span class="hljs-keyword">new</span> Library
{
    Name = <span class="hljs-string">"Central Library"</span>,
    BookShelves = <span class="hljs-keyword">new</span> List&lt;BookShelf&gt;
    {
        <span class="hljs-keyword">new</span> BookShelf
        {
            Number = <span class="hljs-number">1</span>,
            Books = <span class="hljs-keyword">new</span> List&lt;Book&gt;
            {
                <span class="hljs-keyword">new</span> Book
                {
                    Title = <span class="hljs-string">"C# in Depth"</span>,
                    Author = <span class="hljs-string">"Jon Skeet"</span>,
                    YearPublished = <span class="hljs-number">2019</span>
                },
                <span class="hljs-keyword">new</span> Book
                {
                    Title = <span class="hljs-string">"The Pragmatic Programmer"</span>,
                    Author = <span class="hljs-string">"Andy Hunt &amp; Dave Thomas"</span>,
                    YearPublished = <span class="hljs-number">1999</span>
                }
            }
        }
    }
};
</code></pre>
<p>In this example, we can see that libraries are made of bookshelves. But we can also see that bookshelves are composed of books that need to go onto the shelves! This shows multiple levels of composition taking place.</p>
<hr />
<h2 id="heading-benefits-and-considerations-of-composition"><strong>Benefits and Considerations of Composition</strong></h2>
<p>By breaking down complex systems into smaller, reusable components, composition allows for easier code management and promotes code reuse. Now that we’ve seen some code examples showing how this is done, let’s walk through the advantages and considerations for composition.</p>
<h3 id="heading-advantages-of-using-composition"><strong>Advantages of Using Composition</strong></h3>
<ul>
<li><p>Code Reuse: Composition allows us to create smaller, reusable components that can be used in different parts of our codebase. By composing objects together, we can build complex systems by leveraging the functionality and behavior already implemented in those smaller components.</p>
</li>
<li><p>Flexibility: One of the key benefits of composition is the flexibility it provides. We can easily modify the behavior of a system by adding or removing composed objects without impacting the rest of the codebase. This flexibility makes it easier to adapt and extend our software to meet changing requirements.</p>
</li>
<li><p>Maintainability: Composition promotes modular and decoupled code, making it easier to maintain and update. By breaking down a system into smaller components, each responsible for a specific task, we can isolate changes and minimize the impact on other parts of the codebase. This makes our codebase more maintainable and reduces the risk of introducing bugs during updates or modifications.</p>
</li>
<li><p>Testability: When functionality is buried deep in base classes and abstract classes because overuse of inheritance, testing becomes more difficult. Often we need to either implement what is called “fakes” for our tests or we need to get very creative with finding ways to exercise code closer to the base class. With composition often that logic doesn’t need to become as buried and therefore it’s easier to test.</p>
</li>
</ul>
<h3 id="heading-considerations-when-using-composition"><strong>Considerations when Using Composition</strong></h3>
<p>While composition offers numerous benefits, there are some considerations to keep in mind when using it in software design:</p>
<ul>
<li><p>Managing the Lifecycle of Composed Objects: Properly managing the lifecycle of composed objects is important to avoid memory leaks or resource allocation issues. Ensuring that objects are appropriately instantiated and disposed of is important when working with composed systems. In more complex systems, it’s important to understand who owns which dependency — especially if it’s shared.</p>
</li>
<li><p>Interface Usage: I mentioned earlier that composition does not require interfaces, but a side effect can be that people can more easily lean into overusing interfaces. Everything gets an interface! While I do feel that can often help with <a target="_blank" href="https://www.devleader.ca/2021/05/07/tldr-unit-vs-functional-tests/">unit testing</a> — to a certain extent — it can start to become unwieldy when you’re adding them for no purpose just because you see the pattern. I am guilty of this.</p>
</li>
<li><p>“Newing” it all up: When you have to keep passing dependencies in via the constructor to compose objects, where do these all get made? Well, we often find ourselves adding instantiation code the the entry point and this grows out of control. However, you can use dependency injection — things like Autofac or the built-in IServiceCollection — to make this more streamlined.</p>
</li>
</ul>
<hr />
<h2 id="heading-best-practices-for-using-composition-in-c"><strong>Best Practices for Using Composition in C#</strong></h2>
<p>When it comes to using composition in C#, there are several best practices and guidelines that can help you design and organize your code in a clear and efficient manner. Here are some tips to help you make the most out of composition in C#:</p>
<ol>
<li><p>Identify the components: Before you start implementing composition in your code, it’s important to identify the different components or objects that will interact with each other. This will help you determine how to structure your code and which objects should be composed together.</p>
</li>
<li><p>Encapsulate functionality: One of the key benefits of composition is that it allows you to encapsulate functionality within separate objects. Each component should have a well-defined and focused responsibility, making it easier to understand, test, and maintain your code. You heard me sneak in “encapsulation” earlier in the article, and here it is again.</p>
</li>
<li><p>Avoid tight coupling: Composition promotes loose coupling between objects, which helps increase the flexibility and maintainability of your code. Avoid directly instantiating objects within other objects, as this can create tight dependencies. Pass dependencies in via the constructor and consider using interfaces as required.</p>
</li>
<li><p>Favor composition over inheritance: Inheritance can lead to rigid and tightly coupled code. Instead, prefer composition as it allows for more flexible and modular designs. Seriously. It’s more often than not what you’d prefer.</p>
</li>
<li><p>Keep classes small and focused: As you compose objects together, strive to keep your classes small and focused on a single responsibility — enter the Single Responsibility Principle (SRP). This helps make your code more readable, testable, and maintainable. If a class becomes too large or complex, consider breaking it down into smaller, more manageable components. Also, avoid having so many tiny thin classes that you’ve gone to the other extreme.</p>
</li>
<li><p>Use dependency injection: Dependency injection is a powerful technique that complements composition. It allows you to inject dependencies into an object rather than creating them internally. This helps decouple components and makes it easier to swap out dependencies or mock them for testing. We have helpful frameworks to leverage for this!</p>
</li>
</ol>
<p>That’s quite the list — but it’s relatively easy to keep the core idea in mind: You are making objects up from other objects and not inheriting them.</p>
<p><a target="_blank" href="https://dometrain.com/bundle/from-zero-to-hero-csharp?affcode=1115529_nl-teyzg"><img src="https://www.devleader.ca/wp-content/uploads/2024/04/courses-dometrain-C-bundle.webp" alt="C# From Zero to Hero - Dometrain Course" class="image--center mx-auto" /></a></p>
<hr />
<h2 id="heading-wrapping-up-examples-of-composition-in-c"><strong>Wrapping Up Examples of Composition in C#</strong></h2>
<p>To recap, I walked through a handful of simple examples of composition in C# — each trying to use real-world objects to make the examples more understandable. I listed out the benefits, considerations, and even the best practices to follow when it comes to leveraging composition. Remember to use composition to model “is made up of” relationships!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Examples of Inheritance in C# – A Simplified Introduction to OOP]]></title><description><![CDATA[Object-oriented programming (OOP) is a fundamental concept in software engineering — even though the wave of functional programming is upon us! It’s a programming paradigm that allows developers to create modular and reusable code by organizing data ...]]></description><link>https://hashnode.devleader.ca/examples-of-inheritance-in-csharp-a-simplified-introduction-to-oop</link><guid isPermaLink="true">https://hashnode.devleader.ca/examples-of-inheritance-in-csharp-a-simplified-introduction-to-oop</guid><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[inheritance]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[coding]]></category><category><![CDATA[software development]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Thu, 11 Apr 2024 12:00:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1712146117709/d569a1a2-096d-442a-a005-ab3f2f8b5999.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Object-oriented programming (OOP) is a fundamental concept in software engineering — even though the wave of functional programming is upon us! It’s a programming paradigm that allows developers to create modular and reusable code by organizing data and behavior into objects. One key aspect of OOP is inheritance, which allows us to create new classes based on existing classes, inheriting their properties and behaviors. Inheritance, modeling an “is a” relationship, is something many of us learn early in our OOP journey so I wanted to show several examples of inheritance in C# to demonstrate it.</p>
<p>This article is intended for <a target="_blank" href="https://www.devleader.ca/2023/09/20/how-to-learn-coding-for-beginners-what-you-need-to-know/">beginners who want to learn more about inheritance, a</a>nd as always when I discuss inheritance, I am <em>much</em> more in favor of people leaning into composition. I want to acknowledge this bias because, after 20 years of programming, I have personally made the mistake of using inheritance for everything and seen many others do it too. Something to keep in mind as you read through!</p>
<hr />
<h2 id="heading-understanding-inheritance"><strong>Understanding Inheritance</strong></h2>
<p>In object-oriented programming, inheritance is a powerful concept that allows us to define a new class based on an existing class. It enables the new class, called the derived class or subclass, to inherit the properties <a target="_blank" href="https://www.devleader.ca/2023/09/20/how-to-learn-coding-for-beginners-what-you-need-to-know/">and behaviors of the existi</a>ng class, known as the base class or superclass. This inheritance relationship helps to organize and structure code in a meaningful way.</p>
<p>The purpose of inheritance is to promote code reusability and enhance modularity. By inheriting from a base class, we can reuse the code and functionality already defined in it, without having to rewrite it in the derived class. This not only saves time and effort but also promotes consistency across different classes.</p>
<h3 id="heading-real-world-example-to-model-with-inheritance"><strong>Real World Example to Model with Inheritance</strong></h3>
<p>To understand inheritance better, let’s consider a real-world analogy. Think of a car manufacturer that produces different models of cars. Each car model shares common features such as the ability to drive, brake, and accelerate. These common features can be thought of as the base class. The specific car models, such as Sedan, SUV, or Hatchback, can be considered as the derived classes. This is because each of these specific car types have an “is a” relationship to the base — they are all cars!</p>
<p>In the analogy, the base class defines the common features that all car models inherit. The derived classes, on the other hand, can add additional features or modify existing ones to meet their specific requirements. For example, the Sedan class may have additional functionality like a sunroof, while the SUV class could have features like 4-wheel drive.</p>
<h3 id="heading-how-it-works-in-c"><strong>How It Works In C#</strong></h3>
<p>Let’s talk about the very basics here. In C#, we can create a base class using the <code>class</code> keyword and specify the common properties and methods. But how do we represent the “is a” relationship?</p>
<p>We can create derived classes using the <code>:</code> symbol followed by the name of the base class, which effectively says this class “is a” some other class! The derived classes can then add their unique properties and methods while inheriting the ones defined in the base class. By using inheritance, we can create a hierarchy of classes, with each level inheriting and extending the functionality of the previous level.</p>
<p>We can organize our code in a hierarchical manner, which for many developers allows them to push common re-usable code into base classes. One of the arguments is that this helps with reusability and maintenance — following the Don’t Repeat Yourself (DRY) principle — but my own bias suggests this is often not an ideal way to have reusable code. But we’ll see <a target="_blank" href="https://www.devleader.ca/?p=6871">composition in object-oriented programming</a> later.</p>
<p><a target="_blank" href="https://dometrain.com/bundle/from-zero-to-hero-csharp?affcode=1115529_nl-teyzg"><img src="https://www.devleader.ca/wp-content/uploads/2024/04/courses-dometrain-C-bundle.webp" alt="C# From Zero to Hero - Dometrain Course" class="image--center mx-auto" /></a></p>
<hr />
<h2 id="heading-creating-inheritance-relationships-in-c"><strong>Creating Inheritance Relationships in C#</strong></h2>
<p>In object-oriented programming, inheritance allows us to create relationships between classes. With inheritance, we can define a base class that serves as a blueprint, and then create derived classes that inherit properties and methods from the base class.</p>
<p>To create an inheritance relationship between classes in C#, we use the colon (:) symbol. This was described earlier, so let’s take a look at the syntax for declaring a base class and a derived class in this example:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span>
{
    <span class="hljs-comment">// Base class properties and methods</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> : <span class="hljs-title">Shape</span>
{
    <span class="hljs-comment">// Derived class properties and methods</span>
}
</code></pre>
<p>In the example above, the class <code>Shape</code> is the base class, and the class <code>Circle</code> is the derived class. The colon (:) symbol indicates that the <code>Circle</code> class inherits from the <code>Shape</code> class.</p>
<p>When a class inherits from a base class, it automatically inherits all the public and protected properties and methods of the base class. This means that the <code>Circle</code> class will have access to all the properties and methods defined in the <code>Shape</code> class — in this example so far there are none. So let’s continue!</p>
<h3 id="heading-the-virtual-and-override-keywords-in-c"><strong>The Virtual and Override Keywords in C#</strong></h3>
<p>Sometimes, we may want to modify or extend the behavior of a method that is inherited from the base class. In C#, we can do this by using the <code>override</code> keyword along with the <code>virtual</code> keyword. Here’s an example:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Draw</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Base class implementation</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> : <span class="hljs-title">Shape</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Draw</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Derived class implementation</span>
    }
}
</code></pre>
<p>In this example, the <code>Draw</code> method is declared as <code>virtual</code> in the <code>Shape</code> class, which means it can be overridden in derived classes. The <code>Circle</code> class overrides the <code>Draw</code> method and provides its own implementation.</p>
<h3 id="heading-abstract-classes-and-abstract-members-in-c"><strong>Abstract Classes and Abstract Members in C#</strong></h3>
<p>We can use another keyword in C# called <code>abstract</code> to offer different behavior from the base class. If we have an <code>abstract</code> class, the specific type cannot be instantiated, but derived classes inheriting from it can be. <code>Abstract</code> classes can also offer shared functionality by defining members that are accessible to derived classes.</p>
<p>However, <code>abstract</code> classes can also have <code>abstract</code> members! These <code>abstract</code> members, unlike <code>virtual</code> members, do not provide default functionality — so derived classes MUST provide an implementation using the <code>override</code> keyword that we saw previously.</p>
<p>Let’s see that same example with shapes but this time with a twist:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Draw</span>(<span class="hljs-params"></span>)</span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> : <span class="hljs-title">Shape</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Draw</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Derived class implementation that *MUST* be implemented</span>
    }
}
</code></pre>
<p>In the example above, the derived class looks identical to what we saw in the previous example. However, a fundamental difference is that with <code>virtual</code> we could optionally override it — with <code>abstract</code> , we <em>must</em> override and provide an implementation.</p>
<h3 id="heading-accessing-base-class-members-in-c"><strong>Accessing Base Class Members in C#</strong></h3>
<p>To access the members of the base class from the derived class, we use the <code>base</code> keyword. This allows us to call the base class constructor, access base class properties, or invoke base class methods. Here’s an example:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Color { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> : <span class="hljs-title">Shape</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> color</span>)</span>
    {
        <span class="hljs-keyword">base</span>.Color = color; <span class="hljs-comment">// Accessing base class properties</span>
    }
}
</code></pre>
<p>In the above example, the <code>Circle</code> class constructor takes a <code>color</code> parameter and sets the <code>Color</code> property inherited from the base class. This only works with access modifiers more visible than private, otherwise the derived class cannot see the member.</p>
<p>The above example does not require the <code>base</code> keyword, even though it is correct. This is because there is not a conflicting current-scope member called Color that would conflict — the only Color is in the base. If you were overriding a virtual member and wanted to call the base implementation still from your override, this is a great use for explicitly putting the <code>base</code> keyword.</p>
<hr />
<h2 id="heading-practical-scenarios-of-using-inheritance-in-c"><strong>Practical Scenarios of Using Inheritance in C#</strong></h2>
<p>Let’s check out some practical examples of when and how to use inheritance in software development.</p>
<h3 id="heading-modeling-the-relationship-between-employees"><strong>Modeling the Relationship Between Employees</strong></h3>
<p>Let’s consider a scenario where we are building a payroll system for a company. The system needs to handle different types of employees, such as full-time employees, part-time employees, and contractors. Instead of creating separate classes for each type, we can use inheritance to model their relationship. That’s because we can say that each type of employee “is an” employee — that’s an inheritance relationship.</p>
<p>We can create a base class called “Employee” which contains common attributes like name, id, and salary. Then, we can create derived classes like “FullTimeEmployee,” “PartTimeEmployee,” and “Contractor” that inherit from the base “Employee” class. By doing this, we can reuse the common attributes and behaviors defined in the base class, while also adding specific attributes or behaviors unique to each type of employee.</p>
<p>Here’s some example code to show this relationship:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> id,
        <span class="hljs-keyword">decimal</span> salary</span>)</span>
    {
        Name = name;
        Id = id;
        Salary = salary;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span> Salary { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DisplayEmployeeInfo</span>(<span class="hljs-params"></span>)</span>
    {
        Console.WriteLine(<span class="hljs-string">$"Name: <span class="hljs-subst">{Name}</span>, ID: <span class="hljs-subst">{Id}</span>, Salary: <span class="hljs-subst">{Salary}</span>"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">FullTimeEmployee</span> : <span class="hljs-title">Employee</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">FullTimeEmployee</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> id,
        <span class="hljs-keyword">decimal</span> salary</span>) : 
        <span class="hljs-title">base</span>(<span class="hljs-params">name, id, salary</span>)</span>
    {
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PartTimeEmployee</span> : <span class="hljs-title">Employee</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PartTimeEmployee</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> id,
        <span class="hljs-keyword">decimal</span> salary,
        <span class="hljs-keyword">int</span> workingHours</span>) :
        <span class="hljs-title">base</span>(<span class="hljs-params">name, id, salary</span>)</span>
    {
        WorkingHours = workingHours;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> WorkingHours { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DisplayEmployeeInfo</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">base</span>.DisplayEmployeeInfo();
        Console.WriteLine(<span class="hljs-string">$"Working Hours: <span class="hljs-subst">{WorkingHours}</span>"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Contractor</span> : <span class="hljs-title">Employee</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Contractor</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> id,
        <span class="hljs-keyword">decimal</span> salary,
        DateTime contractEndDate</span>) :
        <span class="hljs-title">base</span>(<span class="hljs-params">name, id, salary</span>)</span>
    {
        ContractEndDate = contractEndDate;
    }

    <span class="hljs-keyword">public</span> DateTime ContractEndDate { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DisplayEmployeeInfo</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">base</span>.DisplayEmployeeInfo();
        Console.WriteLine(<span class="hljs-string">$"Contract End Date: <span class="hljs-subst">{ContractEndDate.ToShortDateString()}</span>"</span>);
    }
}
</code></pre>
<p>Can you identify the custom behavior for the derived classes above? What keywords do you need to be looking for?</p>
<h3 id="heading-reusability-and-maintainability"><strong>Reusability and Maintainability</strong></h3>
<p>Inheritance not only allows us to model relationships but also promotes code reuse and maintainability. Consider a scenario where we are developing a game. We can have a base class called “Character” which defines common attributes and methods for all characters in the game, such as health points and attack behavior. Then, we can create derived classes like “Player” and “Enemy” that inherit from the base “Character” class.</p>
<p>By doing this, we can reuse the common attributes and methods defined in the base class, preventing code duplication. Additionally, if we need to make changes to the common attributes or behaviors, we only need to update the code in one place (the base class), which simplifies maintenance and reduces the chances of introducing bugs.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Character</span>
{
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-title">Character</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> healthPoints</span>)</span>
    {
        Name = name;
        HealthPoints = healthPoints;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> HealthPoints { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Attack</span>(<span class="hljs-params">Character target</span>)</span>
    {
        <span class="hljs-comment">// Default attack behavior</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Player</span> : <span class="hljs-title">Character</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Player</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> healthPoints</span>)
        : <span class="hljs-title">base</span>(<span class="hljs-params">name, healthPoints</span>)</span>
    {
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Attack</span>(<span class="hljs-params">Character target</span>)</span>
    {
        <span class="hljs-comment">// Player-specific attack behavior</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Enemy</span> : <span class="hljs-title">Character</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Enemy</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> name,
        <span class="hljs-keyword">int</span> healthPoints</span>)
        : <span class="hljs-title">base</span>(<span class="hljs-params">name, healthPoints</span>)</span>
    {
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Attack</span>(<span class="hljs-params">Character target</span>)</span>
    {
        <span class="hljs-comment">// Enemy-specific attack behavior</span>
    }
}
</code></pre>
<h3 id="heading-design-and-planning-considerations"><strong>Design and Planning Considerations</strong></h3>
<p>When utilizing inheritance in software engineering, proper design and planning are important. It’s important to identify the entities and their relationships, and carefully decide which attributes and behaviors should be included in the base class versus the derived classes. Inheritance should be used with caution, keeping in mind the principle of “favor composition over inheritance” to <a target="_blank" href="https://www.devleader.ca/2013/07/25/how-and-why-to-avoid-excessive-nesting/">avoid excessive</a> class hierarchies and inheritance chains.</p>
<p>While this isn’t a rule, a helpful guideline I find is that if I’m building classes that define logic or algorithms, inheritance is generally a bad fit. I want to compose these systems with other systems. When I’m defining data structures, composition can still be an excellent option, but this is where I find inheritance <em>might</em> be a good fit. As these two statements suggest, composition is more frequently something I find can be used effectively, and it’s actually more rare that I find inheritance a good fit. By following good design principles and leveraging inheritance appropriately, we can create more maintainable and reusable code in our software projects.</p>
<hr />
<h2 id="heading-common-pitfalls-and-best-practices-in-inheritance"><strong>Common Pitfalls and Best Practices in Inheritance</strong></h2>
<p>When working with inheritance in C#, there are some common pitfalls that developers should be aware of to ensure efficient and effective code. Let’s take a look at some of the key considerations.</p>
<h3 id="heading-avoid-deep-inheritance-hierarchies"><strong>Avoid Deep Inheritance Hierarchies</strong></h3>
<p>One common mistake in inheritance is creating deep hierarchies with many levels of subclasses. While it may seem like a good idea at first to divide functionality into smaller subclasses, it can quickly become complex and difficult to maintain. Deep hierarchies can lead to code duplication, increased complexity, and decreased readability. It’s advisable to keep the inheritance hierarchy as shallow as possible to maintain simplicity and flexibility in your code.</p>
<h3 id="heading-understanding-the-is-a-relationship"><strong>Understanding the “is-a” Relationship</strong></h3>
<p>Inheritance is all about creating an “is-a” relationship between classes. It means that a subclass is a specific type of the base class. For example, in a shape hierarchy, a circle is a specific type of shape. This concept is important to the design and implementation of inheritance. Understanding the “is-a” relationship is important to ensure that subclasses inherit the appropriate attributes and behaviors from the base class.</p>
<h3 id="heading-best-practices-for-using-inheritance-effectively"><strong>Best Practices for Using Inheritance Effectively</strong></h3>
<p>To use inheritance effectively and efficiently in C# programming, consider the following best practices:</p>
<ul>
<li><p>Design for Reusability: Inheritance allows you to reuse code from the base class in the subclass. Make sure that the base class is well-designed and provides a solid foundation for the subclasses to build upon. Remember, you don’t need inheritance to be able to re-use code… the purpose of inheritance is to model an “is a” relationship between types.</p>
</li>
<li><p>Prioritize Composition over Inheritance: In some (probably most) cases, composition may be a better choice than inheritance. Instead of using a subclass, consider using composition to create a class that contains instances of other classes. This approach generally provides more flexibility and reduces the coupling between classes. Using an “is made of” relationship instead of an “is a” relationship is very prominent in systems we build, especially when it comes to logic. “is a” relationships for inheritance may be a better fit in representing data transfer objects instead.</p>
</li>
<li><p>Properly Use Abstract Classes and Interfaces: Abstract classes and interfaces play a significant role in inheritance. Abstract classes provide a blueprint for subclasses and can implement common functionality, while interfaces define a contract that classes must adhere to. Remember, if you are just looking for a spot for common code to give consideration if composition will be a better fit instead of just trying to drive more code into a base class.</p>
</li>
<li><p>Avoid Fragile Base Class Problem: The fragile base class problem occurs when modifications to the base class inadvertently break functionality in its subclasses. To avoid this, ensure that changes to the base class, such as adding or modifying methods, do not have an unexpected impact on the subclasses. Again, this becomes a BIG problem when you have complex inheritance hierarchies with logic scattered between the base class and multiple derived classes — and much of the time this can be avoided with composition.</p>
</li>
</ul>
<p>Remember to keep your inheritance hierarchies shallow, understand the “is-a” relationship, and design for reusability. With an understanding of inheritance concepts and best practices, remember to give strong consideration as to whether composition is a better fit. You might just be using inheritance because you feel more comfortable with it instead of for better OOP modeling reasons.</p>
<p><a target="_blank" href="https://dometrain.com/bundle/from-zero-to-hero-csharp?affcode=1115529_nl-teyzg"><img src="https://www.devleader.ca/wp-content/uploads/2024/04/courses-dometrain-C-bundle.webp" alt="C# From Zero to Hero - Dometrain Course" class="image--center mx-auto" /></a></p>
<hr />
<h2 id="heading-wrapping-up-examples-of-inheritance-in-c"><strong>Wrapping Up Examples of Inheritance in C#</strong></h2>
<p>I’m hopeful you caught at least a few instances throughout the article of me recommending that you consider composition over inheritance because truly I do see inheritance get overused. I was responsible for a LOT of code early in my career that overused inheritance and we ultimately had to rewrite a significant portion of it because of how much it crippled our ability to extend the code. It broke most of the guidelines in the best practices section of this article.</p>
<p>With that said though, inheritance has its time and its place. I think if you take the time to understand both of these paradigms you can see how to use them effectively.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Regular Expressions in C#: 3 Examples You Need to Know]]></title><description><![CDATA[If you’re a beginner software developer then you may have already heard about regular expressions, but you might not have been able to put them into practice yet. No fear! In this article, I’ll walk you through 3 very simple examples of regular expre...]]></description><link>https://hashnode.devleader.ca/regular-expressions-in-csharp-3-examples-you-need-to-know</link><guid isPermaLink="true">https://hashnode.devleader.ca/regular-expressions-in-csharp-3-examples-you-need-to-know</guid><category><![CDATA[Regex]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[C#]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Wed, 10 Apr 2024 12:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712441675172/edd28a4e-686a-4299-ab84-08135ea4d0af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’re a beginner software developer then you may have already heard about regular expressions, but you might not have been able to put them into practice yet. No fear! In this article, I’ll walk you through 3 very simple examples of regular expressions in C# to get you started with using them.</p>
<p>No — I won’t be doing a deep dive into complex patterns and super wild and fancy things that you can do with regular expressions. Nope. Just some simple C# examples to get you pointed in the right direction!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-1-regex-starts-with"><strong>1 – Regex Starts With</strong></h2>
<p>When working with regular expressions in C#, you can easily match strings that start with a specific pattern. This can be useful in scenarios where you need to find or extract strings that have a particular prefix. And yeah — I know you’re probably thinking “Hey Nick, don’t we already have <code>string.StartsWith</code> to use?” — and you’re right! But you can’t use that to <a target="_blank" href="https://www.devleader.ca/2024/04/01/regex-options-in-csharp-beginners-guide-to-powerful-pattern-matching/">match patterns</a> more complex than a string directly.</p>
<p>To pattern match at the beginning of a string, you’ll need to use the caret (^) symbol as an anchor in your regular expression pattern. The caret symbol represents the start of a line or string in regular expressions, so by placing it at the beginning of your pattern, you ensure that the match you are looking for occurs at the start of the string.</p>
<p>To demonstrate this, consider the following code example:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

List&lt;<span class="hljs-keyword">string</span>&gt; inputs = <span class="hljs-keyword">new</span>()
{
    <span class="hljs-string">"Hello, World!"</span>,
    <span class="hljs-string">"Something something Hello!"</span>,
    <span class="hljs-string">"  Hello"</span>,
    <span class="hljs-string">"Hello from Dev Leader!"</span>,
};

<span class="hljs-keyword">string</span> pattern = <span class="hljs-string">"^Hello"</span>;
Regex regex = <span class="hljs-keyword">new</span> Regex(pattern);

<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> input <span class="hljs-keyword">in</span> inputs)
{
    Match match = regex.Match(input);
    Console.WriteLine(
        <span class="hljs-string">$"'<span class="hljs-subst">{input}</span>' <span class="hljs-subst">{(match.Success ? <span class="hljs-string">"did"</span> : <span class="hljs-string">"did not"</span>)}</span> "</span> +
        <span class="hljs-string">"match the string starting with the pattern."</span>);
}
</code></pre>
<p>In this example, I’ve <a target="_blank" href="https://www.devleader.ca/2024/03/20/mudblazor-list-items-how-to-create-awesome-blazor-list-views/">created a list</a> of input strings that we can exercise our regular expression against. We’ll use a caret at the beginning of the pattern, which otherwise just says “Hello”, so effectively we’re looking for strings that start with Hello. You can <a target="_blank" href="https://dotnetfiddle.net/dA4MEI">try it out directly in your browser with this DotNetFiddle</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/dA4MEI" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<p>Now a question you <em>should</em> be asking yourself is… is this a good example of using a regular expression instead of string.StartsWith? What do you think the performance of this might be like? Try comparing them in BenchmarkDotNet to find out!</p>
<hr />
<h2 id="heading-2-regex-ends-with"><strong>2 – Regex Ends With</strong></h2>
<p>If you read the previous section: We’re talking about going the other way now. If you didn’t read the previous section: Go read that and then come back and read the first sentence in this section.</p>
<p>Choose your own adventure! And now we can discuss how to match the end of a string with our regex pattern. To match patterns that end with a particular string, we can use the dollar sign ($) symbol as an anchor in our regular expression pattern. The dollar sign represents the end of the string, ensuring that the specified <a target="_blank" href="https://www.devleader.ca/2024/04/01/regex-options-in-csharp-beginners-guide-to-powerful-pattern-matching/">pattern is only matched</a> if it occurs at the end. Basically the opposite of what we saw with the caret symbol.</p>
<p>Let’s consider an example where we want to find all the words in a given text that end with the suffix “ing”. We can achieve this using regular expressions in C# with the following code snippet:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

List&lt;<span class="hljs-keyword">string</span>&gt; inputs = <span class="hljs-keyword">new</span>()
{
    <span class="hljs-string">"Coding"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"I love programming!"</span>, <span class="hljs-comment">// no match</span>
    <span class="hljs-string">"Coding is fun!"</span>, <span class="hljs-comment">// no match</span>
    <span class="hljs-string">"I love programming"</span>, <span class="hljs-comment">// match</span>
};

<span class="hljs-keyword">string</span> pattern = <span class="hljs-string">"ing$"</span>;
Regex regex = <span class="hljs-keyword">new</span> Regex(pattern);

<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> input <span class="hljs-keyword">in</span> inputs)
{
    Match match = regex.Match(input);
    Console.WriteLine(
        <span class="hljs-string">$"'<span class="hljs-subst">{input}</span>' <span class="hljs-subst">{(match.Success ? <span class="hljs-string">"did"</span> : <span class="hljs-string">"did not"</span>)}</span> "</span> +
        <span class="hljs-string">"match the string ending with the pattern."</span>);
}
</code></pre>
<p>Take note of the input strings above because all of them contain “ing” but not all of them end with “ing”. Which ones will match? If you want to try <a target="_blank" href="https://dotnetfiddle.net/0LLhOA">the Regex ends with example in your browser, check out this DotNetFiddle</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/0LLhOA" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<hr />
<h2 id="heading-3-regex-is-match"><strong>3 – Regex Is Match</strong></h2>
<p>While we’ve been looking at comparisons to other string methods like StartsWith and EndsWith, we can continue this comparison with regex in C#. We know that regex will allow us to do more complex <a target="_blank" href="https://www.devleader.ca/2023/10/01/the-builder-pattern-in-c-how-to-leverage-extension-methods-creatively/">pattern matching compared to these string method</a> variations, so what if we simply want to know if there’s a pattern match? If you wanted something similar to <code>string.Contains</code> just to know if a pattern matches a string, we can use the <code>Regex.IsMatch()</code> method to perform the pattern matching.</p>
<p>Note that <code>Regex.IsMatch()</code> will simply return a boolean result instead of a <code>Match</code> type. If you want more information about when your match succeeds, much like in the earlier examples, then you can just use the <code>Match</code> method or even the <code>Matches</code> to get all matching instances within the source string. I wanted to spice it up a bit and use this example just to compare to <code>string.Contains</code>, but if you wanted to compare it to something closer to <code>string.IndexOf</code> to find the position, switch back to the other methods.</p>
<p>If we don’t care about beginning or ending matching, we can ditch the ^ and $ symbols in our regular expressions. Let’s check out this code example that has a slightly more advanced pattern to match:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

List&lt;<span class="hljs-keyword">string</span>&gt; inputs = <span class="hljs-keyword">new</span>()
{
    <span class="hljs-string">"Nick"</span>, <span class="hljs-comment">// no match</span>
    <span class="hljs-string">"Nick1"</span>, <span class="hljs-comment">// no match</span>
    <span class="hljs-string">"1Nick"</span>, <span class="hljs-comment">// no match</span>
    <span class="hljs-string">"Nick42"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"42Nick"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"4Nick2"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"42"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"1337"</span>, <span class="hljs-comment">// match</span>
    <span class="hljs-string">"6"</span>, <span class="hljs-comment">// no match</span>
};

<span class="hljs-keyword">string</span> pattern = <span class="hljs-string">"[0-9]+[a-zA-Z]*[0-9]+"</span>;
Regex regex = <span class="hljs-keyword">new</span> Regex(pattern);

<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> input <span class="hljs-keyword">in</span> inputs)
{
    <span class="hljs-keyword">bool</span> isMatch = regex.IsMatch(input);
    Console.WriteLine(
        <span class="hljs-string">$"'<span class="hljs-subst">{input}</span>' <span class="hljs-subst">{(isMatch ? <span class="hljs-string">"did"</span> : <span class="hljs-string">"did not"</span>)}</span> "</span> +
        <span class="hljs-string">"match the pattern."</span>);
}
</code></pre>
<p>In this example, the <code>Regex.IsMatch()</code> method takes in the <code>input</code> variable and the <code>pattern</code> variable was provided to the <code>Regex</code> instance at creation time. If you examine the pattern that we’re trying to match, we need to have at least 2 numbers with either 0 or many characters from a to z (case not being considered). But what about if we had 2 numbers that were separated by a character that wasn’t in the English alphabet? <a target="_blank" href="https://dotnetfiddle.net/UhguS9">Try it out for yourself with this DotNetFiddle</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/UhguS9" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<hr />
<h2 id="heading-wrapping-up-regular-expressions-in-c"><strong>Wrapping Up Regular Expressions in C#</strong></h2>
<p>As you can see from these examples, regular expressions in C# aren’t so scary, right? They’re just a little bit more complicated than doing some other string operations.</p>
<p>At least, on the surface.</p>
<p>There are <a target="_blank" href="https://www.devleader.ca/2024/04/01/regex-options-in-csharp-beginners-guide-to-powerful-pattern-matching/">regex options in C#</a> to explore and, of course, the regular expressions that we write can get incredibly complex. Regular expressions can be a powerful tool for us to use, but keep in mind that you’ll want to balance things out. Consider readability, performance, and other characteristics if you start heavily relying on regular expressions for matching patterns in your applications!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h1 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h1>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Regex Options In C#: A Beginner’s Guide To Powerful Pattern Matching]]></title><description><![CDATA[Regular expressions are incredibly powerful both at matching string patterns and for giving developers headaches. Some days, I’m not sure what they do a better job of! In C#, when we’re working with regular expressions we get a handful of methods to ...]]></description><link>https://hashnode.devleader.ca/regex-options-in-c-a-beginners-guide-to-powerful-pattern-matching</link><guid isPermaLink="true">https://hashnode.devleader.ca/regex-options-in-c-a-beginners-guide-to-powerful-pattern-matching</guid><category><![CDATA[Regex]]></category><category><![CDATA[C#]]></category><category><![CDATA[coding]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Tue, 09 Apr 2024 12:00:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712437669218/d570bded-e990-4242-98b0-2a23d9751678.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Regular expressions are incredibly powerful both at matching string patterns and for giving developers headaches. Some days, I’m not sure what they do a better job of! In C#, when we’re working with regular expressions we get a handful of methods to use, but we can also configure the regular expressions to behave differently. In this article, we’ll look at regex options in C# together by walking through some introductory regex methods that we have access to and then seeing these regex options in action.</p>
<p>And don’t worry: Not only are there code examples that you can copy and paste, but you can try them out right in your browser thanks to DotNetFiddle.</p>
<hr />
<h2 id="heading-what-is-a-regular-expression"><strong>What is a Regular Expression?</strong></h2>
<p>Regular expressions, often referred to as regex, are powerful tools used for pattern matching in text. They allow you to define a search pattern that can be used to find, replace, or manipulate specific parts of a string. Regular expressions provide a concise and flexible way to search for and identify specific patterns within text data.</p>
<p>In software engineering, <a target="_blank" href="https://www.devleader.ca/?p=6912">regular expressions</a> are particularly useful for tasks such as data validation, text parsing, and pattern extraction. They can be used in a wide range of scenarios, including web development, data processing, and text analysis. Regular expressions can save you time and effort by providing a more efficient and reliable approach to handling text manipulation tasks.</p>
<p>Here are a bunch of practical examples you could consider using a <a target="_blank" href="https://www.devleader.ca/2024/04/02/regular-expressions-in-csharp-3-examples-you-need-to-know/">regular expression</a> for:</p>
<ol>
<li><p><strong>Validating Email Addresses</strong>: Say you are developing a web application that requires users to provide valid email addresses during the registration process. With regular expressions, you can quickly validate if an email address provided by the user adheres to the standard format, ensuring its correctness before further processing.</p>
</li>
<li><p><strong>Searching and Replacing Text</strong>: Imagine you have a large document and need to replace all occurrences of a particular word or phrase with another. Instead of manually searching through the entire document, you can use regular expressions to perform the substitution task efficiently and accurately.</p>
</li>
<li><p><strong>Extracting Data from Text</strong>: Suppose you have a log file containing lines of data, but you are only interested in retrieving specific pieces of information, such as timestamps or error messages. Regular expressions enable you to extract the relevant data by identifying patterns within the log entries, saving you valuable time when analyzing and troubleshooting issues.</p>
</li>
</ol>
<p>These are just a few examples of how regular expressions can be leveraged in your applications. In C#, the .NET framework provides a regex library that offers us the power to match all sorts of strings that we’re interested in. In the following sections, I’ll provide code examples for how to work with regular expressions in C#.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-getting-started-with-regular-expressions-in-c"><strong>Getting Started with Regular Expressions in C#</strong></h2>
<p>To begin using regular expressions in C#, you need to understand how to create and work with Regex objects, which are part of the System.Text.RegularExpressions namespace. So to start, let’s get this namespace included in your C# code. You can do this by adding the following using statement at the top of your C# file:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Text.RegularExpressions;
</code></pre>
<p>Once you have included the namespace, you can create a Regex object to represent your regular expression pattern. The Regex class provides various constructors that allow you to specify the pattern and any additional options — but we’ll just start with the default C# regex options for now. For example, to create a Regex object that matches the word “hello” in a string, you can use the following code:</p>
<pre><code class="lang-csharp">Regex regex = <span class="hljs-keyword">new</span> Regex(<span class="hljs-string">"hello"</span>);
</code></pre>
<h3 id="heading-using-regexmatch-in-c"><strong>Using Regex.Match in C#</strong></h3>
<p>After creating the Regex object, you can use its methods to perform pattern-matching operations on strings. The most commonly used method is <code>Match</code>, which searches for the first occurrence of the pattern in a given string. Here is a basic example that demonstrates how to use regular expressions for pattern matching in C#:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

<span class="hljs-keyword">string</span> input = <span class="hljs-string">"Hello, World!"</span>;
Regex regex = <span class="hljs-keyword">new</span> Regex(<span class="hljs-string">"Hello"</span>);
Match match = regex.Match(input);

<span class="hljs-keyword">if</span> (match.Success)
{
    Console.WriteLine(<span class="hljs-string">$"Pattern found: <span class="hljs-subst">{match.Value}</span>"</span>);
}
<span class="hljs-keyword">else</span>
{
    Console.WriteLine(<span class="hljs-string">"Pattern not found."</span>);
}
</code></pre>
<p>In this example, we create a Regex object to match the word “Hello” and then use the <code>Match</code> method to search for a match in the input string “Hello, World!”. The <code>Match</code> method returns a <code>Match</code> object, which contains information about the first occurrence of the pattern. We can use the <code>Success</code> property to check if a match was found and the <code>Value</code> property to retrieve the matched string.</p>
<p>You can check out <a target="_blank" href="https://dotnetfiddle.net/MnMJzL">this DotNetFiddle to run this C# regex example</a> right in your browser!</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/MnMJzL" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<h3 id="heading-using-regexmatches-in-c"><strong>Using Regex.Matches in C#</strong></h3>
<p>What happens if we want to match more than one part of the input string though? That’s where the <code>Matches</code> method comes into play, which will also give us a <code>MatchCollection</code> return type to work with. Let’s see it in action:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

<span class="hljs-keyword">string</span> input = <span class="hljs-string">"Hello, World!"</span>;
Regex regex = <span class="hljs-keyword">new</span> Regex(<span class="hljs-string">"Hello"</span>);
MatchCollection matches = regex.Matches(input);

<span class="hljs-keyword">if</span> (matches.Count &gt; <span class="hljs-number">0</span>)
{
    Console.WriteLine(<span class="hljs-string">"Pattern(s) found:"</span>);
    <span class="hljs-keyword">foreach</span> (Match match <span class="hljs-keyword">in</span> matches)
    {
        Console.WriteLine(<span class="hljs-string">$"t <span class="hljs-subst">{match.Value}</span>"</span>);
    }
}
<span class="hljs-keyword">else</span>
{
    Console.WriteLine(<span class="hljs-string">"Pattern not found."</span>);
}
</code></pre>
<p>You can see in the example above that if we can enumerate the collection of matches instead of just dealing with a single. And if you want to try it for yourself and experiment, you can <a target="_blank" href="https://dotnetfiddle.net/jXDGrz">use this dotnetfiddle to run the example of Regex.Matches in C#</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/jXDGrz" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<hr />
<h2 id="heading-the-various-regex-options-in-c"><strong>The Various Regex Options in C#</strong></h2>
<p>When working with regular expressions in C#, there are several options that can be used to modify the behavior of the pattern matching. These options are defined by the <code>RegexOptions</code> enumeration in C#. <a target="_blank" href="https://www.devleader.ca/2023/11/15/enums-in-csharp-a-simple-guide-to-expressive-code/">Because this is a flag enum</a>, we can combine the different enum values to mix and match these C# regex options to get the desired behavior we want.</p>
<p>Let’s take a closer look at some commonly used options and understand their use in different scenarios so that you can make informed decisions and leverage regex in C# more effectively!</p>
<h3 id="heading-regexoptionscompiled"><strong>RegexOptions.Compiled</strong></h3>
<p>This option improves performance by precompiling the regular expression pattern into an assembly. It’s especially useful when the same regular expression pattern is used repeatedly. By compiling the pattern once, subsequent matches can be performed more efficiently. To use this option, simply add RegexOptions.Compiled as a parameter when creating your Regex object.</p>
<p>Let’s consider an example where we could <a target="_blank" href="https://www.devleader.ca/2023/03/17/shocking-results-from-collection-and-iterator-benchmarks/">benchmark the results</a> of using this option or not using BenchmarkDotNet:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

<span class="hljs-keyword">using</span> BenchmarkDotNet.Attributes;
<span class="hljs-keyword">using</span> BenchmarkDotNet.Running;

[<span class="hljs-meta">MemoryDiagnoser</span>]
[<span class="hljs-meta">ShortRunJob</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">EmailValidationBenchmark</span>
{
    <span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> you could (should) extend this example</span>
    <span class="hljs-comment">// to try out all sorts of emails and collections</span>
    <span class="hljs-comment">// of emails!</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> TestEmail = <span class="hljs-string">"example@example.com"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> Pattern = <span class="hljs-string">@"^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Regex EmailRegexCompiled = <span class="hljs-keyword">new</span> Regex(
        Pattern,
        RegexOptions.Compiled
    );

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Regex EmailRegexNonCompiled = <span class="hljs-keyword">new</span> Regex(
        Pattern
    );

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">ValidateEmailWithCompiledOption</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> EmailRegexCompiled.IsMatch(TestEmail);
    }

    [<span class="hljs-meta">Benchmark(Baseline = true)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">ValidateEmailWithoutCompiledOption</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> EmailRegexNonCompiled.IsMatch(TestEmail);
    }
}

<span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>)</span>
    {
        <span class="hljs-keyword">var</span> summary = BenchmarkRunner.Run&lt;EmailValidationBenchmark&gt;();
    }
}
</code></pre>
<p>Try this example out — or, better yet, try setting up a benchmark like this for your own regex and seeing if compiled makes a difference for you! Do you notice if there’s a difference in memory usage or just runtime?</p>
<p>Next question for you to try in your benchmarks: Do you want to be creating a new regex with the compiled flag on every time you use it, or is there performance overhead for doing that? Measure it and see if there’s a benefit to doing the compilation of the regex ONCE and storing that regex in an instance variable for re-use!</p>
<h3 id="heading-regexoptionsignorecase"><strong>RegexOptions.IgnoreCase</strong></h3>
<p>This option enables case-insensitive matching, allowing the regular expression pattern to match both uppercase and lowercase characters. This is important to note, because if you weren’t already aware — yes, regex is going to be case-sensitive. Hopefully you haven’t had too many headaches over this yet!</p>
<p>By using this option, when searching for the word “apple” using the pattern “apple”, enabling RegexOptions.IgnoreCase would match “apple”, “Apple”, and “APPLE”. To use this option, include RegexOptions.IgnoreCase as a parameter when creating your Regex object. We can see this in action in the following example:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;


<span class="hljs-keyword">string</span> input1 = <span class="hljs-string">"I love eating apples!"</span>;
<span class="hljs-keyword">string</span> input2 = <span class="hljs-string">"APPLES are great for health."</span>;
<span class="hljs-keyword">string</span> input3 = <span class="hljs-string">"Have you seen my Apple?"</span>;

Console.WriteLine(<span class="hljs-string">$"Input 1 contains 'apple': <span class="hljs-subst">{ContainsApple(input1)}</span>"</span>);
Console.WriteLine(<span class="hljs-string">$"Input 2 contains 'apple': <span class="hljs-subst">{ContainsApple(input2)}</span>"</span>);
Console.WriteLine(<span class="hljs-string">$"Input 3 contains 'apple': <span class="hljs-subst">{ContainsApple(input3)}</span>"</span>);

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">ContainsApple</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> input</span>)</span>
{
    <span class="hljs-comment">// hmmm... should we have pulled this out</span>
    <span class="hljs-comment">// and used the compiled flag?</span>
    Regex appleRegex = <span class="hljs-keyword">new</span> Regex(
        <span class="hljs-string">"apple"</span>,
        RegexOptions.IgnoreCase);
    <span class="hljs-keyword">return</span> appleRegex.IsMatch(input);
}
</code></pre>
<h3 id="heading-regexoptionsmultiline"><strong>RegexOptions.Multiline</strong></h3>
<p>This option changes the behavior of the ^ and $ anchors when used in the pattern. By default, ^ matches the start of the input string and $ matches the end of the input string. However, with RegexOptions.Multiline enabled, ^ also matches the start of each line within the input string and $ matches the end of each line. This option is particularly useful when dealing with multi-line input.</p>
<p>To use this option, include RegexOptions.Multiline as a parameter when creating your Regex object, which you can see in this example below! We’ll use this code to look for lines that start with a comment character denoted by the hashtag/pound symbol, #:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text.RegularExpressions;

<span class="hljs-keyword">string</span> multiLineText = 
    <span class="hljs-string">""</span><span class="hljs-string">"
    This is some sample text.
    # This is a comment.
    And here's another line.
    # Another comment.
    "</span><span class="hljs-string">""</span>;

<span class="hljs-keyword">foreach</span> (<span class="hljs-function"><span class="hljs-keyword">var</span> comment <span class="hljs-keyword">in</span> <span class="hljs-title">FindComments</span>(<span class="hljs-params">multiLineText</span>))</span>
{
    Console.WriteLine(comment);
}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span>[] <span class="hljs-title">FindComments</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> input</span>)</span>
{
    <span class="hljs-comment">// Use RegexOptions.Multiline to treat ^ as the start of each line.</span>
    Regex commentRegex = <span class="hljs-keyword">new</span> Regex(<span class="hljs-string">"^#.*$"</span>, RegexOptions.Multiline);

    <span class="hljs-keyword">var</span> matches = commentRegex.Matches(input);
    <span class="hljs-keyword">string</span>[] comments = <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[matches.Count];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; matches.Count; i++)
    {
        comments[i] = matches[i].Value;
    }

    <span class="hljs-keyword">return</span> comments;
}
</code></pre>
<p>If you want to play around with <a target="_blank" href="https://dotnetfiddle.net/e4X9ZP">this example right in your browser, check out this DotNetFiddle</a>:</p>
<iframe width="100%" height="475" src="https://dotnetfiddle.net/e4X9ZP" style="box-sizing:border-box;margin:0px;padding:0px;border:0px;outline:0px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:inherit;font-variant-east-asian:inherit;font-variant-alternates:inherit;font-variant-position:inherit;font-stretch:inherit;line-height:inherit;font-optical-sizing:inherit;font-kerning:inherit;font-feature-settings:inherit;font-variation-settings:inherit;vertical-align:baseline;font-family:"></iframe>

<hr />
<h2 id="heading-wrapping-up-regex-options-in-c"><strong>Wrapping Up Regex Options in C#</strong></h2>
<p>In this article, I gave you a brief rundown of some simple methods that we have access to in C# for working with regular expressions. But beyond that, we got to see a handful of different regex options in C# that we have access to that can change the behavior of our matching!</p>
<p>Try out the code examples! Play around with them in DotNetFiddle! Consider benchmarking your code with BenchmarkDotNet if you’re looking to tune the performance of your pattern matching using regular expressions in C#.</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Collection Initializer Performance in C# – How To Get An 87% Boost!]]></title><description><![CDATA[After seeing some posts on LinkedIn discussing collection initializers, I became curious. There was a claim that using collection expressions would have better performance than collection initializers. As a result, I set out to measure collection ini...]]></description><link>https://hashnode.devleader.ca/collection-initializer-performance-in-c-how-to-get-an-87-boost</link><guid isPermaLink="true">https://hashnode.devleader.ca/collection-initializer-performance-in-c-how-to-get-an-87-boost</guid><category><![CDATA[performance]]></category><category><![CDATA[C#]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Mon, 08 Apr 2024 12:00:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/imageupload/v1711886913884/40cdd4e7-b32a-4aef-8ad2-a7c5732f957d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After seeing some posts on LinkedIn discussing collection initializers, I became curious. There was a claim that using collection expressions would have better performance than collection initializers. As a result, I set out to <a target="_blank" href="https://www.devleader.ca/2024/03/31/collection-initializer-performance-in-c-double-your-performance-with-what/">measure collection initializer performance in C# using BenchmarkDotNet</a>. And yes, while these might be micro-optimizations for many people, I thought it would be cool to explore.</p>
<p>Besides, maybe there’s someone out there with something like this on their hot-path that needs to squeeze a bit more out of their application 🙂</p>
<hr />
<h2 id="heading-what-are-collection-initializers-and-collection-expressions-in-c"><strong>What Are Collection Initializers and Collection Expressions in C#?</strong></h2>
<p>In one of my most recent articles, I explain <a target="_blank" href="https://www.devleader.ca/2024/03/29/collection-initializers-and-collection-expressions-in-csharp-code-examples/">the basics of collection initializers with some simple code examples</a>. Simple put, instead of manually writing code like the following to initialize a collection:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">string</span>&gt; devLeaderCoolList = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;();
devLeaderCoolList.Add(<span class="hljs-string">"Hello"</span>);
devLeaderCoolList.Add(<span class="hljs-string">", "</span>);
devLeaderCoolList.Add(<span class="hljs-string">"World!"</span>);
</code></pre>
<p>… we can instead reduce it to something more succinct like the following:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">string</span>&gt; devLeaderCoolList = [ <span class="hljs-string">"Hello"</span>, <span class="hljs-string">", "</span>, <span class="hljs-string">"World!"</span> ];
</code></pre>
<p>Pretty neat, right? And this collection expression syntax is even more lightweight than we’ve had access to in recent times.</p>
<p>But syntax and readability aside (Not to minimize the benefits of readability of code, but I’m trying not to put you to sleep), what about the performance?! I bet you didn’t even consider that with all of the different collection initializer syntax that we have that we’d see a performance difference!</p>
<p>Well, Dave Callan got me thinking about that when he posted this on LinkedIn:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/03/collection-initializer-dave-callan-linkedin-benchmark.webp" alt="Dave Callan - Collection Initializer Collection Expression Benchmarks" /></p>
<p><a target="_blank" href="https://www.linkedin.com/feed/update/urn:li:activity:7178702418329624578?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A7178702418329624578%2C7178737535345471492%29&amp;dashCommentUrn=urn%3Ali%3Afsd_comment%3A%287178737535345471492%2Curn%3Ali%3Aactivity%3A7178702418329624578%29">This image was originally posted by Dave Callan on LinkedIn</a>, and that has inspired this entire article. So let’s jump into some benchmarks!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-exploring-list-collection-initializer-performance-in-c"><strong>Exploring List Collection Initializer Performance in C#</strong></h2>
<p>This section will detail the benchmarks for initializing lists in C# in various ways. I’ll provide coverage on different <a target="_blank" href="https://www.devleader.ca/2024/03/29/collection-initializers-and-collection-expressions-in-csharp-code-examples/">collection initializers, the newer collection expression</a> syntax, and even compare it to doing it manually! Surely, adding everything by hand would be slower than setting ourselves up for success by doing it all with a collection initializer — but we should cover our bases.</p>
<p>I will not be covering the spread operator in these benchmarks because I’d like to focus on that more for collection combination benchmarks. Admittedly, yes, it is still creating a collection… but I feel like the use case is different and I’d like to split it up.</p>
<p>I’ll be using BenchmarkDotNet for all of these benchmarks, so if you’re not <a target="_blank" href="https://www.youtube.com/watch?v=Wa3sdKGp3wE">familiar with using BenchmarkDotNet you can check out this video</a> and see how to use it for yourself:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=Wa3sdKGp3wE">https://www.youtube.com/watch?v=Wa3sdKGp3wE</a></div>
<p> </p>
<h3 id="heading-the-list-benchmark-code"><strong>The List Benchmark Code</strong></h3>
<p>With the BenchmarkDotNet NuGet installed, here’s what I am using at the entry point to kick things off (for all benchmark examples in this article):</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> BenchmarkDotNet.Attributes;
<span class="hljs-keyword">using</span> BenchmarkDotNet.Running;

<span class="hljs-keyword">using</span> System.Reflection;

BenchmarkRunner.Run(
    Assembly.GetExecutingAssembly(),
    args: args);
</code></pre>
<p>It’s not very exciting — but I wanted to show you there’s nothing fancy going on here. Just running all of the benchmarks we have access to. And here is the list benchmark code:</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">MemoryDiagnoser</span>]
[<span class="hljs-meta">MediumRunJob</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ListBenchmarks</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span>[] _dataAsArray = <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[]
    {
        <span class="hljs-string">"Apple"</span>,
        <span class="hljs-string">"Banana"</span>,
        <span class="hljs-string">"Orange"</span>,
    };

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> IEnumerable&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">GetDataAsIterator</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> <span class="hljs-string">"Apple"</span>;
        <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> <span class="hljs-string">"Banana"</span>;
        <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> <span class="hljs-string">"Orange"</span>;
    }

    [<span class="hljs-meta">Benchmark(Baseline = true)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ClassicCollectionInitializer_NoCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;()
        {
            <span class="hljs-string">"Apple"</span>,
            <span class="hljs-string">"Banana"</span>,
            <span class="hljs-string">"Orange"</span>,
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ClassicCollectionInitializer_SetCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-number">3</span>)
        {
            <span class="hljs-string">"Apple"</span>,
            <span class="hljs-string">"Banana"</span>,
            <span class="hljs-string">"Orange"</span>,
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CollectionExpression</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span>
        [<span class="hljs-meta">
            <span class="hljs-meta-string">"Apple"</span>,
            <span class="hljs-meta-string">"Banana"</span>,
            <span class="hljs-meta-string">"Orange"</span>,
        </span>];
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CopyConstructor_Array</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;(_dataAsArray);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CopyConstructor_Iterator</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;(GetDataAsIterator());
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAdd_NoCapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        List&lt;<span class="hljs-keyword">string</span>&gt; list = [];
        list.Add(<span class="hljs-string">"Apple"</span>);
        list.Add(<span class="hljs-string">"Banana"</span>);
        list.Add(<span class="hljs-string">"Orange"</span>);
        <span class="hljs-keyword">return</span> list;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAdd_CapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        List&lt;<span class="hljs-keyword">string</span>&gt; list = <span class="hljs-keyword">new</span>(<span class="hljs-number">3</span>);
        list.Add(<span class="hljs-string">"Apple"</span>);
        list.Add(<span class="hljs-string">"Banana"</span>);
        list.Add(<span class="hljs-string">"Orange"</span>);
        <span class="hljs-keyword">return</span> list;
    }
}
</code></pre>
<p>Note in the above code example the baseline we will be comparing against is what I consider the traditional collection initializer:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;()
{
    <span class="hljs-string">"Apple"</span>,
    <span class="hljs-string">"Banana"</span>,
    <span class="hljs-string">"Orange"</span>,
};
</code></pre>
<h3 id="heading-the-list-benchmark-results"><strong>The List Benchmark Results</strong></h3>
<p>And of course, I wouldn’t make you go compile and run these yourself, so let’s look at the results below:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/03/collection-initializer-performance-list-1024x346.webp" alt="C# Collection Initializer and Collection Expression Benchmarks for List" /></p>
<p>Let’s go through the results from worst to best based on the Ratio column (Higher is worse):</p>
<ul>
<li><p>3.31X – Using a copy constructor where we pass in an iterator is the worst performing. This is likely due to the overhead of creating an iterator, especially for such a small and simple overall operation AND because there’s no known capacity when using an iterator.</p>
</li>
<li><p>1.76X – Using a copy constructor even with an array isn’t great. If you know what you need to put into the collection, you’re better off using a normal classic collection initializer. An argument for both the copy constructors though is that if this isn’t on the hot path it might be more maintainable in your code to copy a collection vs instantiate it with duplicated values manually.</p>
</li>
<li><p>1.10X – Manually adding things to a collection without setting a capacity is only a little bit slower than using a collection initializer with no capacity! 10% slower based on these benchmarks.</p>
</li>
<li><p>1.0X – The baseline here is a classic collection initializer with no capacity set</p>
</li>
</ul>
<p>Here is where we start to see some speed up!</p>
<ul>
<li><p>0.64X – Using a collection expression was 64% of the time! That’s a pretty dramatic improvement for what just looks like a syntax change, and that’s very much inline with what Dave Callan’s screenshot shows.</p>
</li>
<li><p>0.61X – Manually adding things to a list that has an initial capacity is actually FASTER than these other collection initializers and collection expression that we’ve seen so far!</p>
</li>
<li><p>0.53X – Using a classic collection initializer but providing the capacity is almost HALF the time!</p>
</li>
</ul>
<p>One of the common themes here is that providing a capacity is a BIG performance gain. We realized an ~87% gain over our baseline simply by providing it a capacity. Side note: why couldn’t the compiler do some kind of optimization here if we know the collection size in the braces?!</p>
<hr />
<h2 id="heading-exploring-dictionary-collection-initializer-performance-in-c"><strong>Exploring Dictionary Collection Initializer Performance in C#</strong></h2>
<p>Dictionaries don’t yet have a fancy collection expression that uses square brackets and removes even more bloat, but we do have several variations of collection initializers to use. These benchmarks will be very similar, also using BenchmarkDotNet, and they also use the same entry point program — so I won’t repeat it here.</p>
<p>I know dictionaries can have two types to work with, and I wanted to keep this similar to the list example — not because they are similar implementations of collections, but because I didn’t want to just pollute this article with more variations of things for no reason. I decided to go with a <code>Dictionary&lt;string, string&gt;</code> where the keys are what we already looked at, and the values are just some short strings to work with that are unique.</p>
<h3 id="heading-the-dictionary-benchmark-code"><strong>The Dictionary Benchmark Code</strong></h3>
<p>Here’s the code for the dictionary benchmarks:</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">MemoryDiagnoser</span>]
[<span class="hljs-meta">MediumRunJob</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DictionaryBenchmarks</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; _sourceData = <span class="hljs-keyword">new</span>()
    {
        [<span class="hljs-meta"><span class="hljs-meta-string">"Apple"</span></span>] = <span class="hljs-string">"The first value"</span>,
        [<span class="hljs-meta"><span class="hljs-meta-string">"Banana"</span></span>] = <span class="hljs-string">"The next value"</span>,
        [<span class="hljs-meta"><span class="hljs-meta-string">"Orange"</span></span>] = <span class="hljs-string">"The last value"</span>,
    };

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> IEnumerable&lt;KeyValuePair&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;&gt; GetDataAsIterator()
    {
        <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> item <span class="hljs-keyword">in</span> _sourceData)
        {
            <span class="hljs-keyword">yield</span> <span class="hljs-keyword">return</span> item;
        }
    }

    [<span class="hljs-meta">Benchmark(Baseline = true)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CollectionInitializer_BracesWithoutCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;()
        {
            { <span class="hljs-string">"Apple"</span>, <span class="hljs-string">"The first value"</span> },
            { <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"The next value"</span> },
            { <span class="hljs-string">"Orange"</span>,  <span class="hljs-string">"The last value"</span> },
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CollectionInitializer_BracesWithCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;(<span class="hljs-number">3</span>)
        {
            { <span class="hljs-string">"Apple"</span>, <span class="hljs-string">"The first value"</span> },
            { <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"The next value"</span> },
            { <span class="hljs-string">"Orange"</span>,  <span class="hljs-string">"The last value"</span> },
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CollectionInitializer_BracketsWithoutCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;()
        {
            [<span class="hljs-meta"><span class="hljs-meta-string">"Apple"</span></span>] = <span class="hljs-string">"The first value"</span>,
            [<span class="hljs-meta"><span class="hljs-meta-string">"Banana"</span></span>] = <span class="hljs-string">"The next value"</span>,
            [<span class="hljs-meta"><span class="hljs-meta-string">"Orange"</span></span>] = <span class="hljs-string">"The last value"</span>,
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CollectionInitializer_BracketsWithCapacity</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;(<span class="hljs-number">3</span>)
        {
            [<span class="hljs-meta"><span class="hljs-meta-string">"Apple"</span></span>] = <span class="hljs-string">"The first value"</span>,
            [<span class="hljs-meta"><span class="hljs-meta-string">"Banana"</span></span>] = <span class="hljs-string">"The next value"</span>,
            [<span class="hljs-meta"><span class="hljs-meta-string">"Orange"</span></span>] = <span class="hljs-string">"The last value"</span>,
        };
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CopyConstructor_Dictionary</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;(_sourceData);
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">CopyConstructor_Iterator</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt;(GetDataAsIterator());
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAdd_NoCapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; dict = [];
        dict.Add(<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"The first value"</span>);
        dict.Add(<span class="hljs-string">"Banana"</span>, <span class="hljs-string">"The next value"</span>);
        dict.Add(<span class="hljs-string">"Orange"</span>, <span class="hljs-string">"The last value"</span>);
        <span class="hljs-keyword">return</span> dict;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAdd_CapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; dict = <span class="hljs-keyword">new</span>(<span class="hljs-number">3</span>);
        dict.Add(<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"The first value"</span>);
        dict.Add(<span class="hljs-string">"Banana"</span>, <span class="hljs-string">"The next value"</span>);
        dict.Add(<span class="hljs-string">"Orange"</span>, <span class="hljs-string">"The last value"</span>);
        <span class="hljs-keyword">return</span> dict;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAssign_NoCapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; dict = [];
        dict[<span class="hljs-string">"Apple"</span>] = <span class="hljs-string">"The first value"</span>;
        dict[<span class="hljs-string">"Banana"</span>] = <span class="hljs-string">"The next value"</span>;
        dict[<span class="hljs-string">"Orange"</span>] = <span class="hljs-string">"The last value"</span>;
        <span class="hljs-keyword">return</span> dict;
    }

    [<span class="hljs-meta">Benchmark</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; <span class="hljs-title">ManuallyAssign_CapacitySet</span>(<span class="hljs-params"></span>)</span>
    {
        Dictionary&lt;<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>&gt; dict = <span class="hljs-keyword">new</span>(<span class="hljs-number">3</span>);
        dict[<span class="hljs-string">"Apple"</span>] = <span class="hljs-string">"The first value"</span>;
        dict[<span class="hljs-string">"Banana"</span>] = <span class="hljs-string">"The next value"</span>;
        dict[<span class="hljs-string">"Orange"</span>] = <span class="hljs-string">"The last value"</span>;
        <span class="hljs-keyword">return</span> dict;
    }
}
</code></pre>
<p>You’ll notice two themes creeping up:</p>
<ul>
<li><p>We have two different flavors of collection initializers: square brackets and curly braces</p>
</li>
<li><p>We can manually instantiate a dictionary by adding or directly assigning (which are NOT the exact same behavior)</p>
</li>
</ul>
<p>Otherwise, we still have capacity considerations just like the list benchmarks!</p>
<h3 id="heading-the-dictionary-benchmark-results"><strong>The Dictionary Benchmark Results</strong></h3>
<p>The dictionary benchmarks are as follows:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/03/collection-initializer-performance-dictionary-1024x388.webp" alt="C# Collection Initializer and Collection Expression Benchmarks for Dictionary" /></p>
<p>Doing the same exercise of highest to lowest ratio:</p>
<ul>
<li><p>2.03X – Copy constructor with iterator strikes again! I suspect for similar reasons — no count for knowing the capacity and the overhead of creating the iterator relative to the number of items.</p>
</li>
<li><p>1.02X – Manually adding items to the dictionary WITH the capacity set was almost the exact same performance as using the collection initializer! This one to me is very surprising given the known capacity usually speeds things up a great deal.</p>
</li>
<li><p>1.0X – Our classic collection initializer using curly braces and not setting the capacity is our baseline</p>
</li>
</ul>
<p>Everything beyond here is technically faster according to our benchmarks:</p>
<ul>
<li><p>0.96X – In the case where we provide a capacity, we’re a little bit faster than the baseline using the same syntax.</p>
</li>
<li><p>0.95X – Manually assigning items without a known capacity is even faster, and about 5% faster than the baseline. I still wouldn’t be making much of a fuss here.</p>
</li>
<li><p>0.94X – Classic collection initializer but using square brackets and not setting a capacity is ~6% faster than the baseline.</p>
</li>
<li><p>0.90X – Manually assigning items when the capacity is known is ~11% faster than the baseline, so we’re starting to pick up steam a little bit here!</p>
</li>
<li><p>0.87X – Classic collection initializer but using square brackets WITH a known capacity is ~15% faster than the baseline</p>
</li>
<li><p>0.86X – Manually adding things to the dictionary but NOT setting a capacity is ~16% faster…</p>
</li>
</ul>
<p>Okay, wait a second. Now we’re going to see that doing a dictionary copy is the FASTEST with a ~35% speed boost? I’m not sure how we’ve started to see known capacities not helping and copy constructors being fastest.</p>
<p>Even I’m skeptical now. So I wanted to rerun the benchmarks and I wanted to add a variant of each of the manual benchmarks that uses <code>new()</code> instead of an empty <a target="_blank" href="https://www.devleader.ca/2024/03/29/collection-initializers-and-collection-expressions-in-csharp-code-examples/">collection expression,</a> <code>[]</code>.</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/03/collection-initializer-performance-dictionary2-1024x386.webp" alt="C# Collection Initializer and Collection Expression Benchmarks for Dictionary V2" /></p>
<p>In this run of the benchmarks, things are much closer across the board. I don’t think that discredits the previous benchmarks, because truly many of them were also relatively close with the iterator copy constructor remaining the huge outlier. But the other huge outlier that remains is the copy constructor using another dictionary!</p>
<p>My takeaway is this:</p>
<ul>
<li><p>For the marginal boost in performance, I think you should opt for readability here — especially when the collection sizes are this small.</p>
</li>
<li><p>If you know that you’re trying to set up a dictionary to be just like another, apparently copying it is much faster. So if you have this kind of thing on a hot path, here’s a fun little micro-optimization.</p>
</li>
</ul>
<hr />
<h2 id="heading-are-these-realistic-benchmarks"><strong>Are These Realistic Benchmarks?</strong></h2>
<p>I’ve written hundreds of articles, made hundreds of YouTube videos, and more posts across social media platforms than I could ever count. There will be people who want to pick these benchmarks apart, and unfortunately, their goal will seem like they’re just trying to discredit what’s being presented.</p>
<p>However, I <em>DO</em> think it’s important to discuss the context of the benchmarks and look at what’s being considered in these scenarios:</p>
<ul>
<li><p>In the grand scheme of things, I’d suspect it’s unlikely that you’re going to get huge performance gains from focusing on these collection initializers. There’s probably bigger fish to fry in your code. But we do see there are some gains to be had!</p>
</li>
<li><p>When using an iterator example with a very small set of data or other very fast operations, the overhead of the iterator itself may dwarf some of the other actions taking place</p>
</li>
<li><p>The use case for these different ways of creating lists varies. For some, we’re defining the full collection whereas for others we’re using values from another collection. The use case isn’t necessarily apples to apples for a comparison.</p>
</li>
<li><p>There seem to be big gains from knowing the capacity up front, which is likely helping reduce collection resizing behind the scenes. How might this change if we were dealing with larger data sets?</p>
</li>
</ul>
<p>The goal of presenting these benchmarks is not to tell you that you must do things a certain way — it’s simply to show you some interesting information. Even if you are hyper-focused on performance, you should benchmark and profile your own code! Don’t rely on my results here. Let these serve as a starting point that you might be able to tune things on your hot path that you didn’t realize.</p>
<p>What other considerations can you think of? Feel free to share in the comments — but be conversational, please.</p>
<hr />
<h2 id="heading-wrapping-up-collection-initializer-performance-in-c"><strong>Wrapping Up Collection Initializer Performance in C#</strong></h2>
<p>Overall, I consider most of what we see in this article on collection initializer performance in C# to be micro-optimizations — more than likely. I wouldn’t lose sleep over using one way over another, as long as you’re optimizing for readability and your profiling results don’t show you spending most of your time doing collection initialization. I hope that you got to have fun exploring this with me and see that if you’re ever curious you can go set up some simple benchmarks to experiment!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h2 id="heading-want-more-dev-leader-content"><strong>Want More Dev Leader Content?</strong></h2>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Collection Initializers And Collection Expressions In C# – Simplified Code Examples]]></title><description><![CDATA[I was recently inspired by some interesting performance characteristics for collection initializers and collection expressions in C#, and I wanted to get an introductory article put together. This article will be part of a small series where I first ...]]></description><link>https://hashnode.devleader.ca/collection-initializers-and-collection-expressions-in-c-simplified-code-examples</link><guid isPermaLink="true">https://hashnode.devleader.ca/collection-initializers-and-collection-expressions-in-c-simplified-code-examples</guid><category><![CDATA[C#]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[coding]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[beginner]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Dev Leader]]></dc:creator><pubDate>Sun, 07 Apr 2024 12:00:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1711855660421/194a62b7-80e6-430b-8c48-cab118dd9fe2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was recently inspired by some interesting performance characteristics for collection initializers and collection expressions in C#, and I wanted to get an introductory article put together. This article will be part of a small series where I first introduce you to the syntax we have to work with for both collection expressions and collection initializers in C#. We’ll see the difference in style and readability — which the dotnet team has been progressing to make the language feel less heavy-handed while still maintaining expressiveness.</p>
<p>Once you’ve got a feel for how collection initializers and collection expressions in C# work, you’ll be geared up to check out some of the performance benchmarks on them. There’s no point in hyper-optimizing for this stuff unless you understand the basics!</p>
<hr />
<h2 id="heading-using-listlttgt-with-collection-initializers-in-c"><strong>Using List&lt;T&gt; with Collection Initializers in C#</strong></h2>
<p>Collection initializers in C# allow for a concise and readable way to populate collections like <code>List&lt;T&gt;</code> upon instantiation. This feature simplifies code by enabling the initialization of a collection with a set of predefined elements without the need for multiple calls to the <code>Add</code> method.</p>
<p>These next subsections will show examples of collection initializers with the <code>List&lt;T&gt;</code> type. Keep in mind that the entire point of these initializers is to define collections with elements in them to start with, which would save us from doing something like the following:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">string</span>&gt; devLeaderCoolList = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;();
devLeaderCoolList.Add(<span class="hljs-string">"Hello"</span>);
devLeaderCoolList.Add(<span class="hljs-string">", "</span>);
devLeaderCoolList.Add(<span class="hljs-string">"World!"</span>);
</code></pre>
<p>So with this as a starting point, consider that the upcoming examples make this feel more streamlined and concise.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<h3 id="heading-example-1-initializing-a-list-of-integers"><strong>Example 1: Initializing a List of Integers</strong></h3>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">int</span>&gt; primeNumbers = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">int</span>&gt; { <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">11</span>, <span class="hljs-number">13</span>, <span class="hljs-number">17</span> };
</code></pre>
<p>This example demonstrates initializing a <code>List&lt;int&gt;</code> with a collection of prime numbers. The numbers are enclosed in braces <code>{}</code> and separated by commas, directly following the instantiation of the list.</p>
<p>We can also use a slightly more short-hand syntax to drop the entire duplicated type definition from the right side of the equal sign:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">int</span>&gt; primeNumbers = <span class="hljs-keyword">new</span>() { <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">11</span>, <span class="hljs-number">13</span>, <span class="hljs-number">17</span> };
</code></pre>
<h3 id="heading-example-2-combining-object-and-collection-initializers"><strong>Example 2: Combining Object and Collection Initializers</strong></h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Student</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Age { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

List&lt;Student&gt; students = <span class="hljs-keyword">new</span> List&lt;Student&gt;
{
    <span class="hljs-keyword">new</span> Student { Name = <span class="hljs-string">"Alice"</span>, Age = <span class="hljs-number">22</span> },
    <span class="hljs-keyword">new</span> Student { Name = <span class="hljs-string">"Bob"</span>, Age = <span class="hljs-number">24</span> }
};
</code></pre>
<p>Here, we combine object and collection initializers to create a <code>List&lt;Student&gt;</code> where each <code>Student</code> object is initialized with <code>Name</code> and <code>Age</code> properties. This approach streamlines the process of filling a collection with fully initialized objects. The important thing to pay attention to here is that the object initializer syntax is very much like the collection initializer syntax, but we are indeed doing two things:</p>
<ol>
<li><p>Assigning values to properties of new objects</p>
</li>
<li><p>Assigning the collection elements upon collection creation</p>
</li>
</ol>
<h3 id="heading-example-3-using-complex-expressions"><strong>Example 3: Using Complex Expressions</strong></h3>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">double</span>&gt; areas = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">double</span>&gt;
{
    Math.PI * Math.Pow(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>),
    Math.PI * Math.Pow(<span class="hljs-number">5</span>, <span class="hljs-number">2</span>)
};
</code></pre>
<p>This example initializes a <code>List&lt;double&gt;</code> with areas of circles (using <code>πr²</code>), where <code>r</code> is the radius. It illustrates that expressions, including method calls, can be used within collection initializers — that is, there is no restriction on constants or pre-evaluated values.</p>
<h3 id="heading-example-4-nested-collection-initializers"><strong>Example 4: Nested Collection Initializers</strong></h3>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Classroom</span>
{
    <span class="hljs-keyword">public</span> List&lt;Student&gt; Students { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

List&lt;Classroom&gt; classrooms = <span class="hljs-keyword">new</span> List&lt;Classroom&gt;
{
    <span class="hljs-keyword">new</span> Classroom
    {
        Students = <span class="hljs-keyword">new</span> List&lt;Student&gt;
        {
            <span class="hljs-keyword">new</span> Student { Name = <span class="hljs-string">"Alice"</span>, Age = <span class="hljs-number">22</span> }
        }
    },
    <span class="hljs-keyword">new</span> Classroom
    {
        Students = <span class="hljs-keyword">new</span> List&lt;Student&gt;
        {
            <span class="hljs-keyword">new</span> Student { Name = <span class="hljs-string">"Bob"</span>, Age = <span class="hljs-number">24</span> }
        }
    }
};
</code></pre>
<p>This example shows how to use nested collection initializers to initialize a list of <code>Classroom</code> objects, each containing a list of <code>Student</code> objects. Very much like Example 2 that we looked at already, but this takes things up one more notch showing multiple collection initializers and object initialization as well.</p>
<h3 id="heading-example-5-simple-list-initialization-with-collection-expressions"><strong>Example 5: Simple List Initialization with Collection Expressions</strong></h3>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions">In C# 11 we start to get some new fancier syntax for collection expressions</a>. This was a step forward in reducing the verbosity of collection declarations using more shorthand similar to other languages. Microsoft says in their documentation:</p>
<blockquote>
<p><em>You can use a collection expression to create common collection values. A collection expression is a terse syntax that, when evaluated, can be assigned to many different collection types. A collection expression contains a sequence of elements between</em> <code>[</code> and <code>]</code> brackets.</p>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions"><em><cite>Microsoft</cite></em></a></p>
</blockquote>
<p>Let’s check out an example:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">int</span>&gt; evenNumbers = [<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span>];
</code></pre>
<p>This example demonstrates the straightforward initialization of a <code>List&lt;int&gt;</code> using the new collection expressions syntax, making the code more concise and readable.</p>
<h3 id="heading-example-6-combining-collections-with-spread-operator"><strong>Example 6: Combining Collections with Spread Operator</strong></h3>
<p>And there are even more goodies in <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions">C# 12 — we get the spread operator for collection initialization</a>:</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">int</span>&gt; firstBatch = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
List&lt;<span class="hljs-keyword">int</span>&gt; combinedList = [<span class="hljs-number">0</span>, ..firstBatch, <span class="hljs-number">4</span>];
</code></pre>
<p>Here, the spread operator <code>..</code> is used to include elements from an existing collection (<code>firstBatch</code>) into a new list, showcasing the flexibility of the new syntax in combining collections seamlessly.</p>
<hr />
<h2 id="heading-where-are-we-headed-with-these"><strong>Where Are We Headed With These?</strong></h2>
<p>As you read through the various code examples, you can decide for yourself which ones offer you the readability that you prefer. There’s not necessarily a right or wrong answer here, but with variety and choice, we are likely going to need to make decisions within our teams about how to stay consistent. Try to strike a balance between minimizing redundancy without hiding too much type information!</p>
<p>But what’s next? Do we care THAT much about readability?</p>
<p>I mean, I do. Honestly, I think it’s incredibly important to prioritize readability in code. But if you’re curious like me, you might see a post like this from <a target="_blank" href="https://www.linkedin.com/in/davidcallan/">Dave Callan</a> on the interwebs and get very curious:</p>
<p><img src="https://www.devleader.ca/wp-content/uploads/2024/03/collection-initializer-dave-callan-linkedin-benchmark.webp" alt="Dave Callan - Collection Initializer Collection Expression Benchmarks" /></p>
<p>And since this is what sparked my interest and caused me to write this article as a primer, you’ll perhaps be interested in the performance characteristics that I investigated!</p>
<hr />
<h2 id="heading-wrapping-up-c-collection-initializers-and-collection-expressions"><strong>Wrapping Up C# Collection Initializers and Collection Expressions</strong></h2>
<p>Now that you’ve seen various examples of the syntax that we have access to, you can make your own informed decisions about which are most readable to you. I think it’s always important to spend some time looking at alternatives so that you can understand different perspectives, even if it seems like it might be minor. Odds are you’re going to read and write collection initializers and collection expressions MANY times in your software engineering career — so why not optimize your choice?</p>
<p>Speaking of optimizations… wait until you see <a target="_blank" href="https://www.devleader.ca/2024/03/31/collection-initializer-performance-in-c-double-your-performance-with-what/">the next article on the performance of collection initializers</a>!</p>
<p>If you found this useful and you’re looking for more learning opportunities, consider <a target="_blank" href="https://subscribe.devleader.ca/">subscribing to my free weekly software engineering newsletter</a> and check out my <a target="_blank" href="https://www.youtube.com/@devleader?sub_confirmation=1">free videos on YouTube</a>! Meet other like-minded software engineers and <a target="_blank" href="https://www.devleader.ca/discord-community-access/">join my Discord community</a>!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://weekly.devleader.ca/embed">https://weekly.devleader.ca/embed</a></div>
<p> </p>
<hr />
<h3 id="heading-want-more-dev-leader-content">Want More Dev Leader Content?</h3>
<ul>
<li><p>Follow along on this platform if you haven’t already!</p>
</li>
<li><p>Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:<br />  <a target="_blank" href="https://subscribe.devleader.ca/"><strong>SUBSCRIBE FOR FREE</strong></a></p>
</li>
<li><p>Looking for courses? Check out my offerings:<br />  <a target="_blank" href="https://devleader.ca/courses"><strong>VIEW COURSES</strong></a></p>
</li>
<li><p>E-Books &amp; other resources:<br />  <a target="_blank" href="https://products.devleader.ca/"><strong>VIEW RESOURCES</strong></a></p>
</li>
<li><p>Watch hundreds of full-length videos on my YouTube channel:<br />  <a target="_blank" href="https://youtube.com/@devleader?sub_confirmation=1"><strong>VISIT CHANNEL</strong></a></p>
</li>
<li><p>Visit my website for hundreds of articles on various software engineering topics (including code snippets):<br />  <a target="_blank" href="https://devleader.ca/"><strong>VISIT WEBSITE</strong></a></p>
</li>
<li><p>Check out the repository with many code examples from my articles and videos on GitHub:<br />  <a target="_blank" href="https://github.com/ncosentino/DevLeader"><strong>VIEW REPOSITORY</strong></a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>