<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-05-02T10:12:13+00:00</updated><id>/feed.xml</id><title type="html">CodingBerry</title><subtitle>A blog by Sami Ramahasindry — documenting the craft of software engineering, one problem at a time.</subtitle><entry><title type="html">A Tale of Garbage Collection</title><link href="/2026/05/01/a-tale-of-gc.html" rel="alternate" type="text/html" title="A Tale of Garbage Collection" /><published>2026-05-01T23:52:00+00:00</published><updated>2026-05-01T23:52:00+00:00</updated><id>/2026/05/01/a-tale-of-gc</id><content type="html" xml:base="/2026/05/01/a-tale-of-gc.html"><![CDATA[<h1 id="the-innocent-dropdown-that-was-eating-our-garbage-collector">The Innocent Dropdown That Was Eating Our Garbage Collector</h1>

<p>There’s a particular kind of bug I love. The kind that’s been sitting in
production for months, where two or three good engineers have already had
a swing at it, and the verdict is always the same shrug: <em>“the database
must be slow during work hours.”</em></p>

<p>This is the story of one of those bugs.</p>

<h2 id="the-symptom">The symptom</h2>

<p>Legacy MVC5 application. A dossier search form, used all day every day by
the backoffice team. Open the page, get a coffee, come back. Painful, but
only between roughly 9 a.m. and 6 p.m. — outside work hours, the page was
fine.</p>

<p>The team had spent weeks on it. Every query plan had been inspected. Every
index reviewed. Every <code class="language-plaintext highlighter-rouge">Include()</code> audited for over-fetching. The DBA had
been consulted. Nothing.</p>

<p>When it landed on my desk, I refused to play the guessing game. Guessing
is how you spend two weeks adding indexes to columns that were never the
problem. I opened my profiler and hit record.</p>

<h2 id="what-the-profiler-actually-said">What the profiler actually said</h2>

<p>The hot path wasn’t a query. It wasn’t EF. It wasn’t the network.</p>

<p>It was a dropdown.</p>

<p>One of those innocent little <code class="language-plaintext highlighter-rouge">&lt;select&gt;</code> controls at the top of the form,
populated with about 1,500 dossiers. The previous developer had built it
the most direct way imaginable: take a string template, do <code class="language-plaintext highlighter-rouge">string.Replace</code>
to inject the id, do another <code class="language-plaintext highlighter-rouge">string.Replace</code> to inject a custom color
based on the dossier’s kind, then <code class="language-plaintext highlighter-rouge">+=</code> the result onto the growing HTML
string. Repeat 1,500 times. Per request.</p>

<p>It looked like this, give or take:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="kt">string</span> <span class="n">html</span> <span class="p">=</span> <span class="s">"&lt;select&gt;"</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">d</span> <span class="k">in</span> <span class="n">dossiers</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">string</span> <span class="n">option</span> <span class="p">=</span> <span class="n">template</span>
        <span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s">"__ID__"</span><span class="p">,</span> <span class="n">d</span><span class="p">.</span><span class="n">Id</span><span class="p">.</span><span class="nf">ToString</span><span class="p">())</span>
        <span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s">"__COLOR__"</span><span class="p">,</span> <span class="nf">ColorFor</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">Kind</span><span class="p">))</span>
        <span class="p">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s">"__LABEL__"</span><span class="p">,</span> <span class="n">d</span><span class="p">.</span><span class="n">Label</span><span class="p">);</span>
    <span class="n">html</span> <span class="p">+=</span> <span class="n">option</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">html</span> <span class="p">+=</span> <span class="s">"&lt;/select&gt;"</span><span class="p">;</span></code></pre></figure>
<p>Every <code class="language-plaintext highlighter-rouge">Replace</code> returns a brand new string. Every <code class="language-plaintext highlighter-rouge">+=</code> allocates a new
string and copies the old one. For 1,500 options that’s something like
6,000 throwaway strings per render, many of them large enough and
long-lived enough to survive Gen 0 and get promoted.</p>

<p>Off-hours, with a couple of users, the GC absorbed it. During work hours,
with thirty users hammering the search form, the heap couldn’t drain fast
enough. Allocations piled up, objects got promoted to Gen 2, and Gen 2
collections — which are the expensive ones — started firing constantly.
The page wasn’t slow because of SQL. It was slow because the GC was
spending most of its time mopping up after this one method.</p>

<p>When old people tell you not to construct large strings with
concatenation, listen.</p>

<h2 id="the-fix">The fix</h2>

<p>The minimum fix is boring: build into a <code class="language-plaintext highlighter-rouge">StringBuilder</code> instead of <code class="language-plaintext highlighter-rouge">+=</code>,
and write the values directly with <code class="language-plaintext highlighter-rouge">Append</code> instead of substituting them
with <code class="language-plaintext highlighter-rouge">Replace</code>. That alone kills the quadratic copy and the throwaway
intermediate strings — Gen 2 collections drop to nearly zero, and you
didn’t add a single dependency.</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="kt">var</span> <span class="n">sb</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">StringBuilder</span><span class="p">(</span><span class="n">dossiers</span><span class="p">.</span><span class="n">Length</span> <span class="p">*</span> <span class="m">80</span><span class="p">);</span>
<span class="n">sb</span><span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"&lt;select&gt;"</span><span class="p">);</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">d</span> <span class="k">in</span> <span class="n">dossiers</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">sb</span><span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"&lt;option value=\""</span><span class="p">).</span><span class="nf">Append</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">Id</span><span class="p">)</span>
      <span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"\" style=\"color:"</span><span class="p">).</span><span class="nf">Append</span><span class="p">(</span><span class="nf">ColorFor</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">Kind</span><span class="p">))</span>
      <span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">";\"&gt;"</span><span class="p">).</span><span class="nf">Append</span><span class="p">(</span><span class="n">d</span><span class="p">.</span><span class="n">Label</span><span class="p">)</span>
      <span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"&lt;/option&gt;"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">sb</span><span class="p">.</span><span class="nf">Append</span><span class="p">(</span><span class="s">"&lt;/select&gt;"</span><span class="p">);</span></code></pre></figure>
<p>I shipped a different fix. I rebuilt the dropdown with <code class="language-plaintext highlighter-rouge">HtmlAgilityPack</code>:
a real DOM, attributes set directly, the document serialized once. It
stops you worrying about a label that happens to contain a quote or an
angle bracket silently producing broken HTML — for a control rendered on
every page load by every user, the correctness was worth the dependency.</p>

<p>Here is what the repro prints on my laptop, 1500 options, 1000 iterations,
16 concurrent renders:</p>
<figure class="highlight"><pre><code class="language-txt" data-lang="txt">[SLOW: string concat + Replace in loop]
  elapsed     :    28914 ms
  allocated   : 203,627.4 MB
  GC Gen0/1/2 : 18083 / 14659 / 14593

[FAST  : StringBuilder, no Replace]
  elapsed     :      120 ms
  allocated   :    546.3 MB
  GC Gen0/1/2 :   49 /   44 /   39

[OK: HtmlAgilityPack]
  elapsed     :     3138 ms
  allocated   :  2,470.4 MB
  GC Gen0/1/2 :  390 /  198 /    6</code></pre></figure>
<p>A few things worth pausing on. The pathological version allocates
<strong>200 GB</strong> over the run and triggers fourteen <em>thousand</em> Gen 2
collections — that’s the GC working full-time, which is exactly what you
felt as page slowness. <code class="language-plaintext highlighter-rouge">StringBuilder</code> is the runaway winner on raw
throughput: 220× faster and 370× less allocated than the original, and
faster than the DOM library too. <code class="language-plaintext highlighter-rouge">HtmlAgilityPack</code> allocates more bytes
but funnels them through short-lived DOM nodes that die in Gen 0, so its
Gen 2 count is the lowest of the three — only 6.</p>

<p>So which is “best” depends on which axis you care about. On every axis,
both are an enormous improvement over the original.</p>

<h2 id="reproducing-it">Reproducing it</h2>

<p>You can reproduce this on whatever you’ve got — Windows, macOS, Linux.
The .NET diagnostic tools ship cross-platform and they’re all you need:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">dotnet-counters</code> — live view of <code class="language-plaintext highlighter-rouge">alloc-rate</code>, <code class="language-plaintext highlighter-rouge">gen-2-gc-count</code>, and
<code class="language-plaintext highlighter-rouge">% time in GC</code>. This alone would have caught the bug.</li>
  <li><code class="language-plaintext highlighter-rouge">dotnet-trace</code> — sampling profiler. Export to speedscope, open the
JSON at speedscope.app, and <code class="language-plaintext highlighter-rouge">String.Replace</code> lights up like a
Christmas tree.</li>
  <li><code class="language-plaintext highlighter-rouge">dotnet-gcdump</code> — heap snapshot, perfect for proving Gen 2 promotion.</li>
  <li>PerfView (Windows) or BenchmarkDotNet (anywhere) for deeper analysis.</li>
  <li>And of course, a commercial profiler like dotTrace or ANTS if you
prefer a GUI — they all show the same thing.</li>
</ul>

<p>I put together a minimal repro in the <a href="https://github.com/jsami/Dropdowngcdemo" target="_blank">companion repo</a>: three versions of
the same dropdown render — the pathological original, the <code class="language-plaintext highlighter-rouge">StringBuilder</code>
fix, and the <code class="language-plaintext highlighter-rouge">HtmlAgilityPack</code> version — with allocation and GC counters
printed at the end. Run it with <code class="language-plaintext highlighter-rouge">dotnet run -c Release</code>. The gap between
the first row and the other two is impossible to miss; which of the two
fixes wins on which metric is its own little surprise.</p>

<h2 id="the-lesson-again">The lesson, again</h2>

<p>The team had been looking under the database streetlight because that’s
where bugs <em>usually</em> are. They weren’t wrong to look there. They were
wrong to keep looking there after the first day.</p>

<p>A profiler doesn’t have opinions. It doesn’t know which code is “supposed
to” be slow. It just tells you where the time went. Spend the ten minutes
to attach one, and it will save you the two weeks of guessing.</p>

<p>Don’t summon magic. Profile.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[There's a particular kind of bug I love. The kind that's been sitting in production for months, where two or three good engineers have already had a swing at it..]]></summary></entry><entry><title type="html">Migration from .Net Framework MVC to Blazor WebAssembly</title><link href="/migration-from-net-framework-mvc-to-blazor-webassembly-faf5937acd2a" rel="alternate" type="text/html" title="Migration from .Net Framework MVC to Blazor WebAssembly" /><published>2023-02-20T11:42:00+00:00</published><updated>2023-02-20T11:42:00+00:00</updated><id>/mvc-fx-to-blazor-wasm</id><content type="html" xml:base="/migration-from-net-framework-mvc-to-blazor-webassembly-faf5937acd2a"><![CDATA[<p>One of the reasons why companies are stuck with old frameworks is how hard it is for them to migrate to a new one. Many factors can contribute to this:</p>

<ul>
  <li>One is that they invested so much in their current product that once it satisfies the business needs, it is out of the question to touch it only for the sake of using a brand-new framework; you know, the adage: “If it works, don’t touch it.”</li>
  <li>Another reason is that they use many platform-specific constructs across all parts of the code base, so everything falls apart when those constructs are unavailable in a newer platform version.
I could cite many reasons why migrating legacy software products is challenging. Still, very often, it boils down to this fact: they were designed without considering changes in the first place. A lot has been written on the subject, so I won’t dwell any further on how to develop software for change; you can find more about this by a simple Google search of the keywords: Clean Code, SOLID principles, Clean Architecture, Refactoring, and so on.</li>
</ul>

<p>Conversely, what could lead a company to migrate the framework they use to construct their product? Well, there aren’t so many reasons. Here are a few:</p>

<h3 id="security-compliance">Security Compliance</h3>
<p>If there is only one reason to migrate, it is this one. It’s because a security breach will cost a lot more to the company than the budget to migrate to a more recent version of the framework that implements the latest security standard available on the market. Also, framework vendors only offer support for the current versions of their products. So, to benefit from vendor support, it’s wiser to migrate to the latest version. You know, the story of Long-Term Support (LTS) and Standard Support.</p>

<h3 id="development-of-significant-new-features">Development of significant new features</h3>
<p>Adding significant changes to the product is also an excellent opportunity to migrate. That way, we mix the migration budget with the new features budget, which can reduce costs overall.</p>

<h2 id="migrating-from-net-framework-mvc-to-blazor-webassembly">Migrating from .Net Framework MVC to Blazor Webassembly</h2>
<p>Let’s talk about the very subject of this blog post: migrating legacy websites created with the .Net framework MVC to Blazor WebAssembly.</p>

<p>Before we begin, note the terms I use in this blog post (and eventually in any of my other posts). Regarding <em>.Net Framework</em>, I mean the .Net version pre-core: the <em>4.x</em> versions. I will use the still-common term <em>.Net Core</em> to refer to the versions that come after. Even if the recent framework versions ditch the “core” part, I guess it’s still convenient when confronting the new versions to the old ones in the same discussion.</p>

<h3 id="migration-strategy">Migration Strategy</h3>
<p>When it comes to migrating legacy software, two approaches are possible:</p>

<ul>
  <li><em>Abrupt Migration</em></li>
</ul>

<p>It consists of redeveloping all the application features with the new framework. Then, when every component has been developed and deployed, the production website will point to the brand-new version.</p>

<p>As you may guess, this risky approach implies a considerable cost and is only suitable for small applications, provided those applications are well-structured. So, for most applications that businesses rely on for their operation, an incremental approach is the way to go.</p>

<ul>
  <li><em>Incremental or Smooth Migration</em></li>
</ul>

<p>It consists of migrating the application to the new framework <em>one subset at a time</em>. Only a subset of the application will be migrated for each iteration.</p>

<p>It implies that components developed with the new framework must integrate seamlessly into the parts designed with the old one. When navigating the website, we won’t know which framework the current page was created.</p>

<h3 id="challenge">Challenge</h3>

<p>Now we have this challenge: How can we <em>seamlessly</em> integrate Blazor components with a web application created with .Net Framework MVC? As you know, Blazor was designed to run natively with .Net Core hosts. Still, a simple Google search will reveal that some people succeed in making a Blazor WebAssembly component work inside a page served by .Net Framework MVC. Most of their methods boil down to the following steps:</p>

<ul>
  <li>Create a Blazor Webassembly application project, where we develop all the new Blazor components.</li>
  <li>Add a post-build event to this project. It will copy the artifact folder <code class="language-plaintext highlighter-rouge">_framework</code> to the root directory of the .Net Framework MVC project.</li>
  <li>Add a <code class="language-plaintext highlighter-rouge">&lt;div id="app" component="ComponentType"&gt;&lt;/div&gt;</code> in any MVC page where we want to add a Blazor component that has a type ComponentType.</li>
  <li>Add a reference to the script <code class="language-plaintext highlighter-rouge">blazor.webassembly.js</code> on the MVC razor page.</li>
  <li>In the Blazor Project, modify the <code class="language-plaintext highlighter-rouge">App.razor</code> <em>root component</em> to render the previous component dynamically.</li>
  <li>Add rules to <code class="language-plaintext highlighter-rouge">web.config</code> to allow the DLLs and other files in the <code class="language-plaintext highlighter-rouge">_framework</code> folder to be loaded as static files by the browsers.</li>
  <li>When we launch the MVC application and navigate to the page where we put the Blazor component, we see that it is rendered correctly, and we can interact with it. Also, when we inspect the Network tab in the browser’s dev tool, we find that all the DLL files inside the <code class="language-plaintext highlighter-rouge">_framework</code> artifact folder are loaded as static files for each page load.</li>
</ul>

<p>You can follow the above steps in this great and informative <a href="https://medium.com/@santiagoc_33226/using-blazor-wasm-with-net-framework-mvc-or-another-old-external-site-7fc0884fcfca" target="_blank">article</a>.</p>

<p>Even if the methods involving the above steps could work, I’m reluctant to adopt them as a basis for the migration. These are the reasons :</p>

<ul>
  <li><em>First of all, the artifact copying step.</em></li>
</ul>

<p>Whenever we need to copy something and then paste it to another location in our software development routine, we should always ask ourselves what could go wrong and whether it is worth it. You might tell me that any build process needs copy-pasting to a specific artifact directory to satisfy the application’s dependencies; I agree. But here is the catch: We are copying the artifact to the root directory of the MVC project (not even to its artifact directory) so that it considers the files inside it as static contents. For this to be possible, we had to tweak the <code class="language-plaintext highlighter-rouge">web.config</code> to allow them to be sent to the client. As you might guess, it smells of security concerns, which is a big one for a security issue! Do you know that leaving the <code class="language-plaintext highlighter-rouge">X-Server</code> HTTP headers to be sent to the client browser gives us a big red high-priority alert during a security test? Well, I will let you guess what kind of alert we will get if we send a bunch of DLLs together with the web page response. This reason alone can make us not consider this approach. As I said in the introductory section, one reason a company would migrate its product to a new framework is Security Compliance; I don’t think that the above approach allows us to achieve this.</p>

<ul>
  <li><em>Removing Blazor routing capability is problematic, too.</em></li>
</ul>

<p>If we decide to use Blazor WebAssembly, it should be for using it at its full potential. That is, taking advantage of all its features, one of which is client-side navigation. That way, we should be capable of navigating through pages that have already been migrated with client-side navigation alone, without page reload. Our goal is to migrate to Blazor WebAssembly; as such, it is crucial not to deprive ourselves of its full potential.</p>

<ul>
  <li><em>Debuggability</em></li>
</ul>

<p>Another major issue with this approach is the debuggability of the resulting solution; it is tough to debug! If a software project is hard to debug, it’s Game Over! Come on; you don’t want to go back to the age of <em>PHP Dump</em>, whereby you print every output of any suspicious code, do you?</p>

<h3 id="stop-and-think">Stop and think</h3>

<p>One important lesson I learned throughout my software developer career is this: <strong><em>“Don’t fight the framework!”</em></strong>. The point of using a framework to develop software is to make our lives easier, and they can only achieve this <em>if we provide minimum requirements</em> for them to function; otherwise, we tend to overcome those requirements with hacks, and that is fighting the framework. In doing so, instead of making our lives easier, the framework combined with the little hacks might make our lives harder.</p>

<p>In our case, the minimum requirement for Blazor WebAssembly for us to build a <strong>sustainable</strong> software solution is <em>.Net Core</em>. Failure to satisfy this requirement is fighting the framework if we persist in using it anyway. The more accurate question is not whether we can integrate Blazor WebAssembly in a .Net Framework MVC project; it is whether we can develop a sustainable software solution with Blazor WebAssembly without .Net Core! To convince you, try to copy the <code class="language-plaintext highlighter-rouge">_framework</code> folder to a static website project and add a reference to the <code class="language-plaintext highlighter-rouge">blazor.webassembly.js</code> file in any HTML file, and don’t forget to add the <code class="language-plaintext highlighter-rouge">div</code> tag with id <code class="language-plaintext highlighter-rouge">"app”</code>; you will find that the page renders the component correctly! But with the caveat that I mentioned previously.</p>

<p>You might tell me: “Hey Sami, are you kidding me? I’ve followed along till here, and now you say that integrating Blazor Webassembly in .Net Framework MVC is fighting the framework?!” I know, I know, you’re right. Just sit back, relax, and keep reading. Everything will make sense at the end of this blog post.</p>

<h3 id="back-to-the-basics-and-embrace-the-framework">Back to the basics and embrace the framework</h3>

<p>So, what options remain for our migration?</p>

<p>When confronted with such challenging situations, I do what I like the most in software engineering: go back to basics and learn from those who know the framework the most. And who knows the framework the most? The vendor, of course! In our case, it’s Microsoft.</p>

<p>After searching through Microsoft .Net documentation, I landed on a page explaining how to migrate a legacy .Net Framework project to the current .Net versions; you can find more about this <a href="https://learn.microsoft.com/en-us/aspnet/core/migration/inc/overview?view=aspnetcore-7.0" target="_blank">here</a>. As we might expect, Microsoft recommends incremental migration for most cases. In doing so, they propose the topology below to migrate the features to the .Net Core solution:</p>

<p><img src="/assets/images/migr_blazor/yarp_topology.png" alt="Migration Topology" class="center-image" /></p>

<p>The game changer is the <a href="https://microsoft.github.io/reverse-proxy/" target="_blank">YARP</a> reverse proxy installed as a Nuget package in the .Net Core app. You can learn more about reverse proxies in this <a href="https://www.youtube.com/watch?v=4NB0NDtOwIQ" target="_blank">nice video</a>.</p>

<p>With this configuration, every incoming request passes through the .Net Core app. If a route is not found at this level, it is forwarded to the legacy site, which will process the request as usual and return the response to the .Net Core app, which produces the response to the client.</p>

<p>In other words, we are now accessing the legacy .Net Framework MVC site through .Net Core! And bingo, we have our ingredient to use Blazor WebAssembly as it should!</p>

<p>Ok, let’s implement this strategy. Fire up Visual Studio and create three projects:</p>

<ul>
  <li><em>BlazorWasm</em> is our Blazor WebAssembly app,</li>
  <li><em>MVCCore</em> is our .Net Core app,</li>
  <li><em>MVCFx</em> is our legacy .Net Framework MVC app.</li>
</ul>

<p>If you have the latest version of Visual Studio, chances are that the template for .Net Framework MVC is unavailable on the list of project templates. If so, there is no need to worry; scroll to the bottom, click  <em>Install more tools and features</em>, and install the template there.</p>

<p><img src="/assets/images/migr_blazor/vs_install_tool.png" alt="Visual Studio Install Tool" class="center-image" /></p>

<p>Once the projects are created, our solution explorer should look like the one below.</p>

<p><img src="/assets/images/migr_blazor/vs_solution_exp_prj.png" alt="Visual Studio Solution Explorer" class="center-image" /></p>

<p>Now, we need to find a way to integrate the Blazor WebAssembly application into the .Net Core application. There is no need to look elsewhere since that is exactly one of the hosting models of Blazor WebAssembly, which is to be <a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hosting-models?view=aspnetcore-7.0#blazor-webassembly" target="_blank">hosted inside a .Net Core application</a>! All we need to do is to install one Nuget package and configure a few middlewares, and bam! Our Blazor application is hosted in our .Net Core App. Isn’t that nice? 😃</p>

<p>To do so, in the MVCCore project:</p>

<ul>
  <li>Add a project reference to the BlazorWasm project;</li>
  <li>Install the WebAssembly Server package:</li>
</ul>
<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="go">Install-Package Microsoft.AspNetCore.Components.WebAssembly.Server</span></code></pre></figure>
<ul>
  <li>In the <code class="language-plaintext highlighter-rouge">Program.cs</code> file, activate WebAssemblyDebugging for Dev mode and activate BlazorFrameworkFiles middleware, which, as its name implies, is responsible for serving the files BlazorWebassembly needs to function client-side:</li>
</ul>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="c1">// [MVC Core] Program.cs</span>
<span class="c1">// ...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">Environment</span><span class="p">.</span><span class="nf">IsDevelopment</span><span class="p">())</span>
<span class="p">{</span>
    <span class="n">app</span><span class="p">.</span><span class="nf">UseWebAssemblyDebugging</span><span class="p">();</span>
<span class="p">}</span>

<span class="n">app</span><span class="p">.</span><span class="nf">UseBlazorFrameworkFiles</span><span class="p">();</span>

<span class="c1">// ...</span></code></pre></figure>
<p>To allow debugging, add the <code class="language-plaintext highlighter-rouge">inspectUri</code> field to the <code class="language-plaintext highlighter-rouge">launchSettings.json</code> for each profile:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="c1">// [MVCCore] launchSettings.json</span></code></pre></figure>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
    </span><span class="nl">"profiles"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"http"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"commandName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Project"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"dotnetRunMessages"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
            </span><span class="nl">"launchBrowser"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
            </span><span class="nl">"inspectUri"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"applicationUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://localhost:5027"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"environmentVariables"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"ASPNETCORE_ENVIRONMENT"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Development"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"https"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"commandName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Project"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"dotnetRunMessages"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
            </span><span class="nl">"launchBrowser"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
            </span><span class="nl">"inspectUri"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"applicationUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://localhost:7020;http://localhost:5027"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"environmentVariables"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"ASPNETCORE_ENVIRONMENT"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Development"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"IIS Express"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"commandName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IISExpress"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"launchBrowser"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
            </span><span class="nl">"environmentVariables"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"ASPNETCORE_ENVIRONMENT"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Development"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>
<p>Again, in the MVCCore project:</p>

<ul>
  <li>Install YARP reverse proxy package</li>
</ul>
<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="go">Install-Package Yarp.ReverseProxy</span></code></pre></figure>
<ul>
  <li>Activate YARP reverse proxy middleware</li>
</ul>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="c1">// [MVCCore] Program.cs</span>

<span class="n">builder</span><span class="p">.</span><span class="n">Services</span><span class="p">.</span><span class="nf">AddReverseProxy</span><span class="p">()</span>
                <span class="p">.</span><span class="nf">LoadFromConfig</span><span class="p">(</span><span class="n">builder</span><span class="p">.</span><span class="n">Configuration</span><span class="p">.</span><span class="nf">GetSection</span><span class="p">(</span><span class="s">"ReverseProxy"</span><span class="p">));</span>

<span class="c1">//...</span>

<span class="n">app</span><span class="p">.</span><span class="nf">MapReverseProxy</span><span class="p">();</span></code></pre></figure>
<p>Add Reverse Proxy configuration to the <code class="language-plaintext highlighter-rouge">appsettings.Development.json</code> file:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
  </span><span class="nl">"Logging"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"LogLevel"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"Default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Information"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"Microsoft.AspNetCore"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Warning"</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"ReverseProxy"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"Routes"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"route1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"ClusterId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"cluster1"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"Match"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"Path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{**catch-all}"</span><span class="w">
        </span><span class="p">}</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="nl">"Clusters"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
      </span><span class="nl">"cluster1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"Destinations"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
          </span><span class="nl">"destination1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"Address"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://localhost:44344/"</span><span class="w"> </span><span class="err">#</span><span class="w"> </span><span class="err">Your</span><span class="w"> </span><span class="err">MVCFx</span><span class="w"> </span><span class="err">URL</span><span class="w"> </span><span class="err">here</span><span class="w">
          </span><span class="p">}</span><span class="w">
        </span><span class="p">}</span><span class="w">
      </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span></code></pre></figure>
<p>The above setting says: <em>“For any route that MVCCore cannot resolve, forward it to the MVCFx application.”</em></p>

<p>To make the MVCFx assets (Content and Scripts) available when accessing it through MVCCore, we need to copy them to the <code class="language-plaintext highlighter-rouge">wwwroot</code> folder of MVCCore. It is OK since those are static contents, commonly accessed as such. We need to make sure that they are in sync between both projects.</p>

<p><img src="/assets/images/migr_blazor/assets_sync.png" alt="Asset Sync" class="center-image" /></p>

<p>In the MVCFx project, we need a way to activate and deactivate Blazor WebAssembly for any specific page. To do so, we turn into our old friend <code class="language-plaintext highlighter-rouge">ViewBag</code> and check a property we’ll call <code class="language-plaintext highlighter-rouge">Blazor</code>, which can be <code class="language-plaintext highlighter-rouge">true</code> or <code class="language-plaintext highlighter-rouge">false</code>, and we set this flag to <code class="language-plaintext highlighter-rouge">true</code> for any page we want to migrate to Blazor WebAssembly. In the <code class="language-plaintext highlighter-rouge">_Layout.cshtml</code>, we will check this flag to render the script referencing <code class="language-plaintext highlighter-rouge">blazor.webassembly.js</code>.</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="c1">// [MVCFx] _Layout.cshtml</span>
<span class="nf">@if</span> <span class="p">(</span><span class="n">ViewBag</span><span class="p">.</span><span class="n">Blazor</span> <span class="p">!=</span> <span class="k">null</span> <span class="p">&amp;&amp;</span> <span class="n">ViewBag</span><span class="p">.</span><span class="n">Blazor</span><span class="p">)</span>
<span class="p">{</span>
    <span class="p">&lt;</span><span class="n">script</span> <span class="n">src</span><span class="p">=</span><span class="s">"_framework/blazor.webassembly.js"</span><span class="p">&gt;&lt;/</span><span class="n">script</span><span class="p">&gt;</span>
<span class="p">}</span></code></pre></figure>
<p>Next, what we need to do is to add the <code class="language-plaintext highlighter-rouge">&lt;div id="app"&gt;&lt;/div&gt;</code> to any MVC page that we need to migrate to Blazor WebAssembly and set the <code class="language-plaintext highlighter-rouge">ViewBag.Blazor</code> flag to <code class="language-plaintext highlighter-rouge">true</code>. Also, in the Blazor WebAssembly project, we created the corresponding page and made sure the <code class="language-plaintext highlighter-rouge">@page</code> route <em><strong>is the same as the path to access the MVC page</strong></em>.</p>

<p>Suppose we want to migrate the Contact page so that instead of displaying the contacts, it will show our famous Blazor Counter page.</p>

<p>In the MVCFx <code class="language-plaintext highlighter-rouge">Contact.cshtml</code> page:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html">//[MVCFx] Contact.cshtml  (path: /Home/Contact)
@{
    ViewBag.Title = "Counter";
    ViewBag.Blazor = true;
}
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"loading-progress-text"</span><span class="nt">&gt;</span>Loading ...<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span></code></pre></figure>
<p>In the BlazorWasm <code class="language-plaintext highlighter-rouge">Counter.razor</code> page:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="c1">// [BlazorWasm] Counter.razor</span>

<span class="o">@</span><span class="n">page</span> <span class="s2">"/home/contact"</span>  <span class="c1">// Make sure this match with the MVCFx page</span>

<span class="o">@</span><span class="n">inject</span> <span class="nc">HttpClient</span> <span class="nc">Http</span>

<span class="o">&lt;</span><span class="nc">PageTitle</span><span class="o">&gt;</span><span class="nc">Counter</span><span class="o">&lt;/</span><span class="nc">PageTitle</span><span class="o">&gt;</span>

<span class="o">&lt;</span><span class="n">h1</span><span class="o">&gt;</span><span class="nc">Counter</span><span class="o">&lt;/</span><span class="n">h1</span><span class="o">&gt;</span>

<span class="o">&lt;</span><span class="n">p</span> <span class="n">role</span><span class="o">=</span><span class="s2">"status"</span><span class="o">&gt;</span><span class="nc">Current</span> <span class="n">count</span><span class="o">:</span> <span class="o">@</span><span class="n">currentCount</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>

<span class="o">&lt;</span><span class="n">button</span> <span class="n">class</span><span class="o">=</span><span class="s2">"btn btn-primary"</span> <span class="o">@</span><span class="n">onclick</span><span class="o">=</span><span class="s2">"IncrementCount"</span><span class="o">&gt;</span><span class="nc">Increment</span><span class="o">&lt;/</span><span class="n">button</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="n">button</span> <span class="n">class</span><span class="o">=</span><span class="s2">"btn btn-primary"</span> <span class="o">@</span><span class="n">onclick</span><span class="o">=</span><span class="s2">"CallWs"</span><span class="o">&gt;</span><span class="nc">Call</span> <span class="nc">Web</span> <span class="nc">Service</span><span class="o">&lt;/</span><span class="n">button</span><span class="o">&gt;</span>

<span class="o">@</span><span class="n">code</span> <span class="p">{</span>
    <span class="k">private</span> <span class="kt">int</span> <span class="n">currentCount</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>


    <span class="k">private</span> <span class="kt">void</span> <span class="nf">IncrementCount</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">currentCount</span> <span class="o">=</span> <span class="n">currentCount</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">private</span> <span class="kt">async</span> <span class="nc">Task</span> <span class="nf">CallWs</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">var</span> <span class="n">response</span> <span class="o">=</span> <span class="n">await</span> <span class="nc">Http</span><span class="mf">.</span><span class="nf">GetAsync</span><span class="p">(</span><span class="s2">"/api/coolservice/giveme"</span><span class="p">);</span>
        <span class="nc">Console</span><span class="mf">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">await</span> <span class="n">response</span><span class="mf">.</span><span class="nc">Content</span><span class="mf">.</span><span class="nf">ReadAsStringAsync</span><span class="p">());</span>
    <span class="p">}</span></code></pre></figure>
<p>One final change to be made to the BlazorWasm project:</p>
<ul>
  <li>In the <code class="language-plaintext highlighter-rouge">MainLayout.razor</code> component, remove all HML elements surrounding the body since, for now, all fixed parts are to be provided by MVCFx. As the migration goes on, we will add some fixed elements.</li>
</ul>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="c1">// [BlazorWasm] MainLayout.razor</span>

<span class="o">@</span><span class="n">inherits</span> <span class="nc">LayoutComponentBase</span>

<span class="o">@</span><span class="nc">Body</span></code></pre></figure>
<ul>
  <li>To avoid being redirected to the Blazor Index.razor page when we click on the Home link while on a Blazor Page, we must ensure that its page directive is not “/” anymore. We may also delete it since it is of no use for now. Our home page is still the MVCFx one.</li>
</ul>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="c1">// [BlazorWasm] Index.razor</span>

<span class="o">@</span><span class="n">page</span> <span class="s2">"/blazor-index"</span> <span class="c1">// To avoid that we are redirected to this page when we click on a Home link</span>

<span class="o">&lt;</span><span class="nc">PageTitle</span><span class="o">&gt;</span><span class="nc">Index</span><span class="o">&lt;/</span><span class="nc">PageTitle</span><span class="o">&gt;</span>

<span class="o">&lt;</span><span class="n">h1</span><span class="o">&gt;</span><span class="nc">Hello</span><span class="p">,</span> <span class="n">world</span><span class="o">!&lt;/</span><span class="n">h1</span><span class="o">&gt;</span>

<span class="nc">Welcome</span> <span class="n">to</span> <span class="n">your</span> <span class="k">new</span> <span class="nc">app</span><span class="mf">.</span>

<span class="o">&lt;</span><span class="nc">SurveyPrompt</span> <span class="nc">Title</span><span class="o">=</span><span class="s2">"How is Blazor working for you?"</span> <span class="o">/&gt;</span></code></pre></figure>
<p>Now, it’s time to run our solution!</p>

<p>To make this work, <em><strong>both the MVCCore and MVCFx projects need to run at the same time</strong></em>. To do this, right-click on the solution, select Properties, then Startup Project, and then choose Multiple Startup Projects, as shown below.</p>

<p><img src="/assets/images/migr_blazor/project_startup.png" alt="Project Startup" class="center-image" /></p>

<p>Now, you can run the solution as usual; both of the projects will run at the same time.</p>

<p>Go to the browser where the MVCFx is running; the home page is displayed:</p>

<p><img src="/assets/images/migr_blazor/mvc_fx_home.png" alt="MVC FX Home" class="center-image" /></p>

<p>In MVCCore app, navigate to <code class="language-plaintext highlighter-rouge">/Home/Contact</code>. We see the famous <code class="language-plaintext highlighter-rouge">Counter</code> component displayed!</p>

<p><img src="/assets/images/migr_blazor/counter_inside_fx.png" alt="Counter inside MVC FX" class="center-image" /></p>

<p>Now, here is how it works:</p>

<ul>
  <li>When we try to access the page at <code class="language-plaintext highlighter-rouge">/Home/Contact</code>, the .Net Core app won’t find the route configured, so, with the help of YARP reverse proxy, it forwards the request to the legacy site.</li>
  <li>The legacy site will return the page since it exists on its side. Since we’ve activated Blazor for the page, the <code class="language-plaintext highlighter-rouge">blazor.webassembly.js</code> file will be loaded (note that we didn’t need to copy anything for it to be available; the .Net Core app serves it as this one acts as the host for the Blazor WebAssembly app!), also since the page has the <code class="language-plaintext highlighter-rouge">&lt;div id="app"&gt;&lt;/div&gt;</code>, Blazor will render the App root component at this place.</li>
  <li>Now, Blazor WebAssembly sees the current route <code class="language-plaintext highlighter-rouge">/Home/Contact</code> and finds out it is available for the Counter Page so that it will be rendered! Nice huh? 😃</li>
</ul>

<p>With this approach:</p>

<ul>
  <li>DLLs Loading is more efficient. No needless redownload on each page load.</li>
  <li>Debugging works as it should since Blazor WebAssembly is served through .Net Core.</li>
  <li>No Cors issues when we perform AJAX calls to the API endpoints inside the .Net Core application since the request is made on the same domain.</li>
</ul>

<p>Et voilà!</p>

<p>Maybe I missed some steps to make the above strategy work, but feel free to fork <a href="https://github.com/jsami/LegacyMigrationGithub" target="_blank">the repos of the solution</a> and make some comparisons.</p>

<h2 id="bottom-line">Bottom Line</h2>

<p>In this blog post, we scratched the surface of how we could migrate from a .Net Framework MVC project to Blazor WebAssembly. Nevertheless, it is far from the whole picture for the migration, but as the Chinese philosopher Lao Tzu said: <em><strong>“The journey of a thousand miles begins with one step,”</strong></em> and if any first step needs to be made, it’d better be the good one. I hope this blog post inspired you to begin your long and challenging journey of legacy project migration.</p>

<p>Cheers!</p>]]></content><author><name></name></author><category term="dotnet" /><category term="asp.net" /><category term="mvc" /><category term=".netcore" /><category term="blazor" /><category term="webassembly" /><category term="migration" /><category term="yarp" /><summary type="html"><![CDATA[One of the reasons why companies are stuck with old frameworks is how hard it is for them to migrate to a new one. Many factors can contribute to this ...]]></summary></entry><entry><title type="html">Closure in C#</title><link href="/closure-in-c-5c106ed95795" rel="alternate" type="text/html" title="Closure in C#" /><published>2020-02-02T17:04:00+00:00</published><updated>2020-02-02T17:04:00+00:00</updated><id>/csharp-closure</id><content type="html" xml:base="/closure-in-c-5c106ed95795"><![CDATA[<h2 id="assumptions">Assumptions</h2>
<p>In this blog post, I’m allowing myself to assume that:</p>
<ol>
  <li>You know the C# programming language (or any programming language that supports anonymous methods like JavaScript, for example) and</li>
  <li>Your code already uses delegates and lambda expressions (or anonymous methods).</li>
</ol>

<h2 id="motivation">Motivation</h2>

<p>Delegates and Lambda expressions are so lovely:</p>
<ul>
  <li>They make our code more concise and facilitate some tasks that would otherwise be complex and cumbersome.</li>
  <li>The introduction of delegates to the C# language allowed us to treat functions as <em>first-class citizens</em>, assign functions to variables, take functions as arguments of another function, or return a function from another function.</li>
  <li>Used with LINQ (Language Integrated Query), they offer powerful tools to process data in our daily programming tasks.</li>
  <li>And so on.</li>
</ul>

<p>As with any powerful tool, though, there are some basic concepts that we need to understand to avoid the subtle bugs lurking in our codebase. One concept that gives lambda expressions their power is the concept of <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#capture-of-outer-variables-and-variable-scope-in-lambda-expressions" target="_blank"><strong>Closure</strong></a>.</p>

<h2 id="what-is-a-closure">What is a closure?</h2>
<p>Let’s perform a few experiments with lambda expressions.</p>

<h4 id="experiment-1">Experiment 1</h4>

<p>Let’s suppose we have the code below:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ClosureCsharp</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span> <span class="p">=</span> <span class="m">5</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="p">=</span> <span class="m">2</span><span class="p">;</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="n">f</span> <span class="p">=</span>  <span class="n">y</span> <span class="p">=&gt;</span> <span class="n">y</span> <span class="p">*</span> <span class="n">n</span><span class="p">;</span>
    
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">x</span><span class="p">}</span><span class="s"> x </span><span class="p">{</span><span class="n">n</span><span class="p">}</span><span class="s"> = </span><span class="p">{</span><span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">)}</span><span class="s">"</span><span class="p">);</span>
    
    <span class="n">n</span> <span class="p">=</span> <span class="m">3</span><span class="p">;</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"After assignment."</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">x</span><span class="p">}</span><span class="s"> x </span><span class="p">{</span><span class="n">n</span><span class="p">}</span><span class="s"> = </span><span class="p">{</span><span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">)}</span><span class="s">"</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>When running this code snippet, we get the output below:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">5 x 2 <span class="o">=</span> 10
After assignment
5 x 3 <span class="o">=</span> 15</code></pre></figure>
<p>Great! We got the correct result as we expected. But how?</p>

<p>As we all know, the scope evaluation inside a C# code block is from top to bottom: any declaration or assignment of variables is <em>visible</em> to subsequent expressions following this declaration/assignment inside this block, but an expression that uses a specific variable would not be <em>aware</em> of any future assignment to this variable. Thus, after the assignment <code class="language-plaintext highlighter-rouge">int n = 2</code>, normally, we might think that the code at line <code class="language-plaintext highlighter-rouge">7</code> would be translated to:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="n">Func</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="n">f</span> <span class="p">=</span>  <span class="n">y</span> <span class="p">=&gt;</span> <span class="n">y</span> <span class="p">*</span> <span class="m">2</span><span class="p">;</span></code></pre></figure>
<p>and any future assignment of <code class="language-plaintext highlighter-rouge">n</code> after this line would not affect the value of <code class="language-plaintext highlighter-rouge">f</code>. But why did the assignment <code class="language-plaintext highlighter-rouge">n = 3</code> cause the behavior of <code class="language-plaintext highlighter-rouge">f</code> to change? Well, as you might be expecting, the answer is <strong>Closures</strong>.</p>

<p>What is happening in line <code class="language-plaintext highlighter-rouge">7</code> is that the lambda expression captures the variable <code class="language-plaintext highlighter-rouge">n</code> in a <em>context</em> so that every modification on <code class="language-plaintext highlighter-rouge">n</code> would have an impact on the function <code class="language-plaintext highlighter-rouge">f</code>. This process is called <strong>variable capturing</strong>: the context “closes over” the variable, hence the name <em>closure</em>.</p>

<p><img src="/assets/images/cs_closure/context_1.png" alt="Context 1" class="center-image" /></p>

<p>As the picture above shows, the <em>delegate</em> <code class="language-plaintext highlighter-rouge">f</code> will refer to the created context. Any assignment to the variable <code class="language-plaintext highlighter-rouge">n</code> would impact this context, hence changing the behavior of <code class="language-plaintext highlighter-rouge">f</code>.</p>

<p>In line <code class="language-plaintext highlighter-rouge">11</code>, after the assignment <code class="language-plaintext highlighter-rouge">n = 3</code>, the captured variable will be updated to 3.</p>

<p><img src="/assets/images/cs_closure/context_2.png" alt="Context 2" class="center-image" /></p>

<p>That is how we get the correct answer: <code class="language-plaintext highlighter-rouge">5 x 3 = 15</code>.</p>

<p>Also, it’s worth noting that the compiler performs this context creation at compile-time and is completely transparent to the programmer. How it is implemented will vary by the scope of the variable captured (a local variable, an instance variable, a method argument, etc.) and any optimization performed by the compiler. The context often is implemented as a private class, and each delegate invocation is translated into the call to an instance method on an object created from this class. You may find more details about this in Jon Skeet’s book <em>C# in Depth</em>.</p>

<h4 id="experiment-2">Experiment 2</h4>
<p>As the Motivation section discusses, functions are first-class citizens in C# using delegates and lambda expressions. As such, they can be assigned to variables (as we’ve already done), passed as method arguments, and returned by methods. So now, let’s suppose that the lambda expression is provided by a helper function <code class="language-plaintext highlighter-rouge">MultiplierBy()</code>:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ClosureCsharp</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span> <span class="p">=</span> <span class="m">5</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="p">=</span> <span class="m">2</span><span class="p">;</span>
    <span class="n">Func</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="n">f</span> <span class="p">=</span> <span class="nf">MultiplierBy</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>

    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">x</span><span class="p">}</span><span class="s"> x </span><span class="p">{</span><span class="n">n</span><span class="p">}</span><span class="s"> = </span><span class="p">{</span><span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">)}</span><span class="s">"</span><span class="p">);</span>

    <span class="n">n</span> <span class="p">=</span> <span class="m">3</span><span class="p">;</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">x</span><span class="p">}</span><span class="s"> x </span><span class="p">{</span><span class="n">n</span><span class="p">}</span><span class="s"> = </span><span class="p">{</span><span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">)}</span><span class="s">"</span><span class="p">);</span>
  <span class="p">}</span>
  
  <span class="k">static</span> <span class="n">Func</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="nf">MultiplierBy</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> 
  <span class="p">{</span>
    <span class="k">return</span> <span class="n">y</span> <span class="p">=&gt;</span> <span class="n">y</span> <span class="p">*</span> <span class="n">n</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Which give us the output:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">5 x 2 <span class="o">=</span> 10
5 x 3 <span class="o">=</span> 10</code></pre></figure>
<p>Damn! Wrong answer after the assignment at line <code class="language-plaintext highlighter-rouge">11</code>!</p>

<p>I want to raise two points from this experiment:</p>
<ul>
  <li>
    <p>First, at line <code class="language-plaintext highlighter-rouge">7</code>, even if we’ve declared a delegate and it gets its value from a helper function, no variable capturing has been performed. It enforces that variable capturing is a compiler trick, and it happens once and for all at compile time, not at runtime. The compiler would create the “capturing context” only when it finds a declaration of a delegate using a lambda expression (or an anonymous method), which refers to variables <em>visible</em> to this declaration, leading us to our second point.</p>
  </li>
  <li>
    <p>Variable capturing has been performed inside the <code class="language-plaintext highlighter-rouge">MultiplierBy()</code> helper function. Here, the context captures the parameter <code class="language-plaintext highlighter-rouge">n</code> of this method, not the variable <code class="language-plaintext highlighter-rouge">n</code> declared at line <code class="language-plaintext highlighter-rouge">6</code>. Then, this context has been returned to the calling method and assigned to the delegate <code class="language-plaintext highlighter-rouge">f</code>. The image below depicts this process:</p>
  </li>
</ul>

<p><img src="/assets/images/cs_closure/context_3.png" alt="Context 3" class="center-image" /></p>

<p><br />
After the assignment at line <code class="language-plaintext highlighter-rouge">11</code>, we have the situation below:</p>

<p><img src="/assets/images/cs_closure/context_4.png" alt="Context 4" class="center-image" /></p>

<p>Here, <code class="language-plaintext highlighter-rouge">n</code> is outside the context referred by <code class="language-plaintext highlighter-rouge">f</code>; hence, any assignment performed to <code class="language-plaintext highlighter-rouge">n</code> won’t impact <code class="language-plaintext highlighter-rouge">f</code>.</p>

<h4 id="experiment-3-multiple-variable-capture">Experiment 3: multiple variable capture</h4>
<p>In this last experiment, let’s consider this code snippet:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ClosureCsharp</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;</span> <span class="n">actions</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;();</span> 
    <span class="k">for</span> <span class="p">(</span><span class="kt">var</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">&lt;</span> <span class="m">10</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
    <span class="p">{</span>
      <span class="kt">var</span> <span class="n">msg</span> <span class="p">=</span> <span class="s">$"Do action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
      <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">msg</span><span class="p">));</span>
    <span class="p">}</span>
    
    <span class="k">foreach</span><span class="p">(</span><span class="kt">var</span> <span class="n">action</span> <span class="k">in</span> <span class="n">actions</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="nf">action</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Here, we declare a list of <code class="language-plaintext highlighter-rouge">Action</code> delegates. A <code class="language-plaintext highlighter-rouge">for</code> loop is used to populate this list, and then a <code class="language-plaintext highlighter-rouge">foreach</code> loop is used to iterate over this list to call each <code class="language-plaintext highlighter-rouge">Action</code>.</p>

<p>When running this code, we get the output:</p>
<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="gp">Do action #</span>0
<span class="gp">Do action #</span>1
<span class="gp">Do action #</span>2
<span class="gp">Do action #</span>3
<span class="gp">Do action #</span>4
<span class="gp">Do action #</span>5
<span class="gp">Do action #</span>6
<span class="gp">Do action #</span>7
<span class="gp">Do action #</span>8
<span class="gp">Do action #</span>9</code></pre></figure>
<p>Great! So far, so good.
Once again, it may seem more or less evident that we got the correct result, but let’s examine what is happening inside the <code class="language-plaintext highlighter-rouge">for</code> loop.</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="k">for</span> <span class="p">(</span><span class="kt">var</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">&lt;</span> <span class="m">10</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
  <span class="kt">var</span> <span class="n">msg</span> <span class="p">=</span> <span class="s">$"Do action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
  <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">msg</span><span class="p">));</span>
<span class="p">}</span></code></pre></figure>
<p>Here, as we know, till this point, since the lambda expression is using the variable <code class="language-plaintext highlighter-rouge">msg</code>, a context will be created to capture this variable.
Visually, this can be described as follows:</p>
<ol>
  <li>First, the compiler sees that the lambda expression uses a variable it “sees” in its scope. The compiler will then create a “mold” of the context to be used:
<img src="/assets/images/cs_closure/context_mold.png" alt="Context Mold" class="center-image" /></li>
  <li>Since <code class="language-plaintext highlighter-rouge">msg</code> is declared for each iteration, an <em>instance</em> of this context is created for each iteration, and each context contains a different “version” of <code class="language-plaintext highlighter-rouge">msg</code>.
<img src="/assets/images/cs_closure/multiple_context.png" alt="Multiple Context" class="center-image" /></li>
  <li>For each iteration, a reference to a context is added to the <code class="language-plaintext highlighter-rouge">actions</code> collection.</li>
</ol>

<p>Hence, when we iterate over the <code class="language-plaintext highlighter-rouge">actions</code> collection, we iterate over the created contexts (or closures).</p>

<p>Now, let’s modify a little bit our code:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ClosureCsharp</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;</span> <span class="n">actions</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;();</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">&lt;</span> <span class="m">10</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
    <span class="p">{</span>
      <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Do action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">));</span>
    <span class="p">}</span>

    <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">action</span> <span class="k">in</span> <span class="n">actions</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="nf">action</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>In line <code class="language-plaintext highlighter-rouge">9</code>, we’ve decided to save a line of code by passing directly the interpolated string to the lambda expression without using a temporary variable <code class="language-plaintext highlighter-rouge">msg</code>.
Removing a temporary variable won’t hurt that much, huh? Well, let’s see what this will give us as output:</p>
<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10
<span class="gp">Do action #</span>10</code></pre></figure>
<p>Phew! Once again, it’s closures in action. This one is among the subtleties that give us a headache when debugging a codebase that uses a lot of lambda expressions inside loops.</p>

<p>So, what’s going on here? Well, let’s take a look at the <code class="language-plaintext highlighter-rouge">for</code> loop again:</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">&lt;</span> <span class="m">10</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
    <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Do action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">));</span>
<span class="p">}</span></code></pre></figure>
<p>As previously mentioned, variable capturing occurs inside the <code class="language-plaintext highlighter-rouge">for</code> loop, but this time, it’s the turn of the variable <code class="language-plaintext highlighter-rouge">i</code> to be captured. 
Since the variable <code class="language-plaintext highlighter-rouge">i</code> is visible for each iteration of the <code class="language-plaintext highlighter-rouge">for</code> loop, multiple contexts are still created, but they all share a reference to this captured variable. Visually, this can be seen as follows:</p>

<p><img src="/assets/images/cs_closure/shared_captured.png" alt="Shared captured variable" class="center-image" /></p>

<p>So, any update on the value of <code class="language-plaintext highlighter-rouge">i</code> will impact all the created contexts. Since the final value of <code class="language-plaintext highlighter-rouge">i</code> is 9, all the contexts capturing <code class="language-plaintext highlighter-rouge">i</code> will share this value. That’s why we got the repeated text as output.</p>

<p>Now, let’s push this experiment a little bit forward.</p>
<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre><span class="k">public</span> <span class="k">class</span> <span class="nc">ClosureCsharp</span>
<span class="p">{</span>
  <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
  <span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;</span> <span class="n">actions</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">Action</span><span class="p">&gt;();</span>  
    <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p">&lt;</span> <span class="m">10</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
    <span class="p">{</span>
      <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Do action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">));</span>
    <span class="p">}</span>

    <span class="n">i</span> <span class="p">=</span> <span class="m">11</span><span class="p">;</span>

    <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Do outside action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">));</span>

    <span class="n">i</span> <span class="p">=</span> <span class="m">12</span><span class="p">;</span>
    
    <span class="n">actions</span><span class="p">.</span><span class="nf">Add</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Do another outside action #</span><span class="p">{</span><span class="n">i</span><span class="p">}</span><span class="s">"</span><span class="p">));</span>
    
    <span class="n">i</span> <span class="p">=</span> <span class="m">13</span><span class="p">;</span>

    <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">action</span> <span class="k">in</span> <span class="n">actions</span><span class="p">)</span>
    <span class="p">{</span>
      <span class="nf">action</span><span class="p">();</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></figure>
<p>Here, in line <code class="language-plaintext highlighter-rouge">6</code>, we’ve declared the variable <code class="language-plaintext highlighter-rouge">i</code> outside the <code class="language-plaintext highlighter-rouge">for</code> loop so that it will be accessible outside of it. And in lines <code class="language-plaintext highlighter-rouge">14</code> and <code class="language-plaintext highlighter-rouge">18</code>, we’ve added two other actions to the <code class="language-plaintext highlighter-rouge">actions</code> list. Both of those outside actions refer to the variable <code class="language-plaintext highlighter-rouge">i</code>. Before iterating over the <code class="language-plaintext highlighter-rouge">actions</code> collection, we assign 13 to <code class="language-plaintext highlighter-rouge">i</code>. That gives us the output below:</p>
<figure class="highlight"><pre><code class="language-console" data-lang="console"><span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do action #</span>13
<span class="gp">Do Outside action #</span>13
<span class="gp">Do another Outside action #</span>13</code></pre></figure>
<p>Once again, both outside lambda expressions captured the variable <code class="language-plaintext highlighter-rouge">i</code>, so they will share it with the ten others created inside the <code class="language-plaintext highlighter-rouge">for</code> loop (as shown in the picture below). As we may now expect, the assignment of value 13 to the captured variable before iterating over the <code class="language-plaintext highlighter-rouge">actions</code> collection will impact every closure sharing it.</p>

<p><img src="/assets/images/cs_closure/shared_captured2.png" alt="Shared captured variable" class="center-image" /></p>

<h2 id="bottom-line">Bottom line</h2>
<p>As seen in this blog post, closures are significant elements to be considered when using lambda expressions (or anonymous methods) in our code. They make lambda expressions as intuitive as possible, but care should always be taken, mainly when used inside loops.</p>]]></content><author><name>Sami</name></author><category term="dotnet" /><category term="c#" /><category term="linq" /><category term="closure" /><category term="lambda-expression" /><category term="functional-programming" /><summary type="html"><![CDATA[With any powerful tool, there are some basic concepts that we need to understand to avoid that subtle bugs lurk in our codebase. One of those basic concepts that give lambda expressions their power is Closure.]]></summary></entry></feed>