<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: El cat bot</title>
    <description>The latest articles on DEV Community by El cat bot (@elcatbot).</description>
    <link>https://dev.to/elcatbot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2600638%2F2979ada9-00fd-4255-9a68-53e1d747d5a7.jpg</url>
      <title>DEV Community: El cat bot</title>
      <link>https://dev.to/elcatbot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elcatbot"/>
    <language>en</language>
    <item>
      <title>Understanding Constants in C#: CLR perspective</title>
      <dc:creator>El cat bot</dc:creator>
      <pubDate>Sat, 12 Jul 2025 00:14:10 +0000</pubDate>
      <link>https://dev.to/elcatbot/understanding-constants-in-c-clr-perspective-36cp</link>
      <guid>https://dev.to/elcatbot/understanding-constants-in-c-clr-perspective-36cp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Applications often require specific values that do not change at runtime. For example variables containing values such as number of months in a year, PI number, Euler number, etc. Since these values are referenced by different modules, it could be catastrophic if they're modified by threads or processes. The C# language helps to avoid this situations by including constants.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is a Constant?
&lt;/h1&gt;

&lt;p&gt;A constant is a value assigned at compile time and will never be modified at runtime, meaning it won't change for the whole application lifetime.&lt;/p&gt;

&lt;p&gt;A constant must be declared using the &lt;em&gt;const&lt;/em&gt; keyword and primitive types (int, bool, decimal, double, byte, char, string, etc.). Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyMathClass
{ 
    public const double Pi = 3.1416;
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The correct way to call a constant value is by indicating its Type as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string message = $"The PI number is { MyMathClass.PI }";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned above, a constant value is defined at compile-time. Therefore, the compiler will throw an error if any piece of code tries to modify it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb3lezj3wcoh0tn0ocbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb3lezj3wcoh0tn0ocbs.png" alt=" " width="202" height="34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By using constants, values will be preserved for the whole application lifetime process. &lt;/p&gt;

&lt;p&gt;There's a question to be answered, why are constant values called as static fields and not through objects?&lt;/p&gt;

&lt;h2&gt;
  
  
  Compile-time constant definition
&lt;/h2&gt;

&lt;p&gt;Due to their immutable nature, the compiler saves constant's value in the assembly metadata. This makes them static members rather than instance members. &lt;/p&gt;

&lt;p&gt;When code calls a constant, the compiler directly checks in the metadata and gets the constant's value to embed it into the IL (Intermediate Language) code. Let's see this by printing the PI constant using Console.WriteLine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyMathClass
{ 
    public const double PI = 3.1416;
} 

public void Main()
{
    Console.WriteLine(MyMathClass.PI);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IL Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IL_0000 nop 
IL_0001 ldc.r8  A7 E8 48 2E FF 21 09 40  // 3.1416
IL_000A call    Console.WriteLine (Double)
IL_000F nop 
IL_0010 ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;IL_0001 ldc.r8&lt;/em&gt;, the compiler is just loading the value into the evaluation stack and then calls &lt;em&gt;IL_000A call&lt;/em&gt; to print it. It will be imbedded everywhere it is called.&lt;/p&gt;

&lt;p&gt;A comparison can be made by turning PI into a class field and calling it through a object instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyMathClass
{ 
    public double PI = 3.1416;
} 

void Main()
{
    MyMathClass myClass = new();
    Console.WriteLine(myClass.PI);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compilation generates a slightly different IL code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Main ()
IL_0000 nop 
IL_0001 newobj  MyMathClass..ctor
IL_0006 stloc.0    // myClass
IL_0007 ldloc.0    // myClass
IL_0008 ldfld   MyMathClass.PI
IL_000D call    Console.WriteLine (Double)
IL_0012 nop 
IL_0013 ret 

// MyMathClass..ctor
IL_0000 ldarg.0 
IL_0001 ldc.r8  A7 E8 48 2E FF 21 09 40  // 3.1416
IL_000A stfld   MyMathClass.PI
IL_000F ldarg.0 
IL_0010 call    Object..ctor
IL_0015 nop 
IL_0016 ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In &lt;em&gt;IL_0001 newobj&lt;/em&gt; of Main(), an instance of MyMathClass is being created. There, PI constant is assigned to 3.1416 (it calls &lt;em&gt;MyMathClass..ctor&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;IL_0006 stloc.0&lt;/em&gt; and &lt;em&gt;IL_0007 ldloc.0&lt;/em&gt; store the object into a local variable and load the object into the evaluation stack. &lt;/li&gt;
&lt;li&gt;Finally, in &lt;em&gt;IL_0008 ldfld&lt;/em&gt;, PI value is loaded from the object and &lt;em&gt;IL_000D call&lt;/em&gt; prints it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;Again, C# constants are defined into IL code, meaning that there's no memory allocation for it at runtime. Knowing this, it's worth pointing out that because an address does not exist for constants, they cannot be passed by reference (ref keyword).&lt;/p&gt;

&lt;p&gt;If a constant is modified (a different value) and the method calling the constant is in a different assembly (.dll), the application must be completely recompiled. Consider the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F772bqsz3ybs8gnl82q2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F772bqsz3ybs8gnl82q2d.png" alt=" " width="742" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PI constant is defined within MyMathClass, which is also defined in Assembly 2.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Main method is within Program class, which is contained in Assembly 1. This method calls and prints PI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When both .dll compile together, Console.WriteLine(PI) in Main method is taking 3.1416 value in IL code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  But what would happen if PI is updated to 3.15?
&lt;/h3&gt;

&lt;p&gt;If for some reason PI is now equal to 3.15 instead of 3.1416, Assembly 1 calling PI constant must be recompiled along with Assembly 2. That's because PI's value is updated at compile time and not at runtime. The following image explains the situation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg2gky3m7wjjxjcyhdft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg2gky3m7wjjxjcyhdft.png" alt=" " width="763" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After Assembly 2 recompiles, PI constant is now 3.15, so a decision process is shown, asking if Assembly 1 has been recompiled. If recompiled along with Assembly 2, PI constant in Main method updates to 3.15, if not, PI remains 3.1416. It would be a disaster for future calculations because it has a different value in each part of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The .NET CLR helps with immutability when a value needs to remain the same throughout application's lifetime. Constant values are good approach written in C# and then treated as a static member by the compiler. &lt;/p&gt;

&lt;p&gt;It's worth mentioning that a constant value is imbedded intro every IL code call. Therefore, this value must be immutable. &lt;/p&gt;

&lt;p&gt;If for some reason it needs to be modified, it's recommended to replace the constant for a read-only field. Read-only fields assign values at runtime, meaning that there is no need for full application recompilation. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;CLR via C# &lt;em&gt;by Jeffrey Richter&lt;/em&gt; offers tons of information about type members.&lt;/p&gt;

&lt;p&gt;Happy Learning =);&lt;/p&gt;

</description>
      <category>clr</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Understanding the .NET CLR: What Every C# Developer Should Know</title>
      <dc:creator>El cat bot</dc:creator>
      <pubDate>Sat, 05 Jul 2025 17:44:43 +0000</pubDate>
      <link>https://dev.to/elcatbot/understanding-the-net-clr-what-every-c-developer-should-know-1me8</link>
      <guid>https://dev.to/elcatbot/understanding-the-net-clr-what-every-c-developer-should-know-1me8</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Every day of developer's career, interaction with a programming language is the way to compile and run applications. If no errors found, it just executes and performs its job.&lt;/p&gt;

&lt;p&gt;Sometimes, new to intermediate developers have asked themselves at least one of the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens when code is compiled?&lt;/li&gt;
&lt;li&gt;is CPU able to understand C# code?&lt;/li&gt;
&lt;li&gt;How variables, objects are handled in memory?&lt;/li&gt;
&lt;li&gt;What does "Run" mean?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions before are completely valid. To answer them, .NET has a powerful platform doing so much work behind the scenes: The CLR.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the CLR?
&lt;/h1&gt;

&lt;p&gt;.NET CLR (Common Language Runtime) is the engine of the .NET environment where C# code is compiled and executed. Every application built on ASP.NET Core MVC, WinForms, MAUI, etc, needs a runtime to execute. It supports different programming languages such as C#, Visual Basic, F#, C++/CLI, among others. That's why the "Common Language" part of the name.&lt;/p&gt;

&lt;p&gt;To put it simple, the CLR is a virtual machine that handles very important tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C# code compilation into IL (Common Intermediate Language)&lt;/li&gt;
&lt;li&gt;Code execution by JIT (Just-in-Time compiler)&lt;/li&gt;
&lt;li&gt;Memory management by GC (Garbage Collector)&lt;/li&gt;
&lt;li&gt;Exception handling&lt;/li&gt;
&lt;li&gt;Thread management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is worth mentioning that C# code is just text. A platform needs to bring C# code to life. That is CLR's job.&lt;/p&gt;

&lt;h2&gt;
  
  
  CLR code flow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wkv5somowjvq72yz846.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wkv5somowjvq72yz846.png" alt=" " width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of those processes occur when a developer runs an application.&lt;/p&gt;

&lt;p&gt;Taking into account the previous flow, now, questions at the beginning can be answered:&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when code is compiled?
&lt;/h2&gt;

&lt;p&gt;After developers hit compile or execute "dotnet build" command, CLR transforms C# code into IL code and stores it in a .dll or .exe file. This file contains all IL code and metadata necessary for the JIT compiler to read. It is worth pointing out that IL is CPU independent, meaning it has to be translated later.&lt;/p&gt;

&lt;h2&gt;
  
  
  is CPU able to understand C# code?
&lt;/h2&gt;

&lt;p&gt;No, CPU cannot read C# nor IL code. That leads us to think about how machine can read code. CLR is perfectly aware of this, which is why it has a specialized compiler called JIT (Just-in-Time). When application starts, JIT takes all the IL code from .dll files, performs optimizations and loads native machine code into memory. Now, CPU threads can execute instructions in code they can understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  How variables, objects are handled in memory?
&lt;/h2&gt;

&lt;p&gt;Once program code is running, information about objects and their values need an storage location. That's the job for: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Stack&lt;/li&gt;
&lt;li&gt;Garbage Collector (GC) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Value types (int, bool, decimal, etc ) and local variables in a method execution go directly to the Stack. The Stack is a LIFO (Last-in, First-out) storage. It allows two operations: adding data on the top (push) and returning data from the top (pop). This model is perfect for local variables to be disposed immediately after the method finishes. Think about a method doing Sum operation as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public int Sum(int a, int b) =&amp;gt; a + b;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mention before, integers are value types and they are loaded to the Stack for fast execution. Therefore, the Sum of "a" and "b" is performed and the result is returned. Afterward, "a" and "b" are unloaded from the Stack:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4uh1ts3em34wyjzk3un.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4uh1ts3em34wyjzk3un.png" alt=" " width="800" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For reference types (objects), the GC communicates to the OS to reserve memory and create a location where .NET objects will reside. This location is the GC Managed Heap. There, reference types and static objects are allocated. The managed heap is divided into segments called generations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generation 0 (G0)&lt;/li&gt;
&lt;li&gt;Generation 1 (G1)&lt;/li&gt;
&lt;li&gt;Generation 2 (G2)&lt;/li&gt;
&lt;li&gt;Generation 3 or Large Object Heap (LOH)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i95u0rdh0y41qanjcro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i95u0rdh0y41qanjcro.png" alt=" " width="635" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's say there is an existing class called MyType. When creating an instance of MyType:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var myType = new MyType();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It goes directly to G0. The "new" keyword tells the compiler to add the necessary metadata to allocate this reference type, right on the Managed Heap.&lt;/p&gt;

&lt;p&gt;It is worth noting that G0, G1 and G2 are also known as Small Object Heap (SOH). Together, GC and JIT allocate objects into SOH if object size is &amp;lt;= 85000 bytes. Otherwise, they go to the LOH. &lt;/p&gt;

&lt;p&gt;When JIT needs to allocate a new object, it "asks" GC to retrieve a memory address, if there is no space on the managed heap, GC performs a Collection. It means, it releases memory by getting rid of unused objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does "Run" mean?
&lt;/h2&gt;

&lt;p&gt;When a dotnet application is executing previous CLR steps, it is running. That simple. On application startup, CLR performs IL compilation once, JIT compilation every time a method is called for the first time and memory management by allocating-collecting objects. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The CLR is a massive engine (almost invisible to developers) that powers all .NET Applications. It's important to start delving into CLR fundamentals to write better code. For example, when experiencing performance issues, it's better to understand how Garbage Collector works to detect memory leaks. Therefore, the problem could be a Managed Heap full of objects and likely in C# code level. &lt;/p&gt;

&lt;h1&gt;
  
  
  What's next?
&lt;/h1&gt;

&lt;p&gt;Start reading about CLR implementation to understand this interesting but important topic. The following Microsoft documentation and books are packed with concepts to help digging deeper into CLR code and architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The book of the Runtime: &lt;a href="https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/README.md" rel="noopener noreferrer"&gt;https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/README.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pro .NET Memory Management &lt;em&gt;by Konrad Kokosa&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The Garbage Collection Handbook &lt;em&gt;by Richard Jones, Antony Hosking&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;CLR via C# &lt;em&gt;by Jeffrey Richter&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;.NET IL Assembler &lt;em&gt;by Serge Lidin&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clr</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>C# Delegates, the basics</title>
      <dc:creator>El cat bot</dc:creator>
      <pubDate>Fri, 04 Jul 2025 00:14:43 +0000</pubDate>
      <link>https://dev.to/elcatbot/basics-of-delegates-46fn</link>
      <guid>https://dev.to/elcatbot/basics-of-delegates-46fn</guid>
      <description>&lt;p&gt;In C#, we have a powerful feature that can help us reference methods for future execution. This implementation is the Delegate type. &lt;/p&gt;

&lt;p&gt;Specifically, it defines methods, parameters and return type. Think about delegates as Callback method that it is passed into other methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ordinary Method call.
&lt;/h2&gt;

&lt;p&gt;Let's say We are writing a program that needs to make a discount calculation based on a client membership type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic: 10%&lt;/li&gt;
&lt;li&gt;Premium: 30%&lt;/li&gt;
&lt;li&gt;No-membership: 0%
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public decimal GetDiscount(decimal price, string customerType)
{
    if(customerType == "Basic")
    {
        return price = price * 0.90M;
    }
    else if(customerType == "Premium")
    {
        return price = price * 0.70M;
    }
    else
    {
        return price;
    }
}

var price = GetDiscount(450, "Premium");

Console.WriteLine(price); // 315.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After passing a price of 450, discount will be 315. GetDiscount works but if we think about validations, this method shouldn't have to validate that the customer has a membership or not. In terms of Single Responsibility SOLID principle, GetDiscount should only have to calculate discount and return the value. That's all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delegate implementation
&lt;/h2&gt;

&lt;p&gt;Fortunately, it is possible to add a delegate to clean up our code:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Declare the delegate:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public delegate decimal Calculation(decimal price);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's worth pointing out that this delegate is a method wrapper. Delegate signature must match with our GetDiscount method. So, method return type and parameters must be equals to the delegate. &lt;/p&gt;

&lt;h4&gt;
  
  
  2. Modify GetDiscount to receive only Calculation delegate as a parameter:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public decimal GetDiscount(Calculation calculation, decimal price)
{
    return calculation(price);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note our code is reduced to one line of code. That's because GetDiscount performs discount and method logic will be added as parameter when GetDiscount is called.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Call GetDiscount and pass our delegate and price as parameters:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GetDiscount(price =&amp;gt; price * 0.90M, 450); // 405.00

GetDiscount(price =&amp;gt; price * 0.70M, 450); // 315.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When calling GetDiscount, the first parameter will be our discount delegate using anonymous function. Instead of writing discount process in GetDiscount, we pass it as parameter to be invoked later. The second parameter is price.&lt;/p&gt;

&lt;p&gt;The Complete code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public delegate decimal Calculation(decimal price);

public void Main()
{
    var discountBasic = GetDiscount(price =&amp;gt; price * 0.90M, 450);
    var discountPremium =  GetDiscount(price =&amp;gt; price * 0.70M, 450);

    Console.WriteLine("Having a price of 450: ");
    Console.WriteLine($"    Premium membership has a discount =&amp;gt; {discountBasic}");
    Console.WriteLine($"    Basic membership has a discount  =&amp;gt; {discountPremium}");
}

public decimal GetDiscount(Calculation calculation, decimal price)
{
    return calculation(price);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multicast Delegate
&lt;/h2&gt;

&lt;p&gt;There are situations where we have call more than one implementation, one after another, and each method shares signature (same return type, same parameters). &lt;/p&gt;

&lt;p&gt;Let's say we have a program that creates an User and after that, it calls three methods to log a message to Local File, Azure and AWS cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void LogToAWS(string message)
{
    // Save to AWS Cloud....
    Console.WriteLine($"AWS =&amp;gt; {message}");
}

public void LogToFile(string message)
{
    // File.Write....
    Console.WriteLine($"File =&amp;gt; {message}");
}

public void LogToAzure(string message)
{
    // Save to Azure Cloud....
    Console.WriteLine($"Azure =&amp;gt; {message}");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A CreateUser method calls each Log implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void CreateUser()
{
    // Create User logic...
    // User created
    var message = "User created Successfully";

    LogToAWS(message);
    LogToFile(message);
    LogToCloud(message);
}

// AWS =&amp;gt; User created Successfully
// File =&amp;gt; User created Successfully
// Azure =&amp;gt; User created Successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's perfectly working but what happens if new Log destinations are added. For example ElasticSearch and more. It wouldn't be clean adding more methods that do the same thing for different providers. &lt;/p&gt;

&lt;p&gt;With Multicast delegates we can declare a class containing a delegate and a centralized method that invokes it. Let's see how it works:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Declare LogHandler delegate:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public delegate void LogHandler(string message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Create MyLogger class:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyLogger
{
    public LogHandler Log;

    public void LogMessage(string message)
    {
        Log?.Invoke(message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we declare MyLogger class, a local delegate called LogHandler and LogMessage method. Our method accepts the message and then invokes our delegate with "Log?.Invoke()" syntax. See the method signature is still the same as all the previous Log methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Modify CreateUser method to call our delegate:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void CreateUser()
{
    // Create User logic...
    // User created
    var message = "User created Successfully";

    var myLogger = new MyLogger();

    myLogger.Log +=  (message) =&amp;gt; 
    { 
        // Send to AWS Cloud....
        Console.WriteLine($"AWS =&amp;gt; {message}");
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we created and instance of MyLogger class, this is where our delegate "Log" is located. After that, we assign our LogToAWS function using anonymous function. You may be asking "What happened with LogToAWS method?". We got rid of it. Why? Although is completely right to call it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myLogger.Log += LogToAWS;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's cleaner to assign an anonymous function for readability. But it's up to you how to call it.&lt;/p&gt;

&lt;p&gt;Then we call LogMessage method and pass our message to invoke our function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Execute Delegate
myLogger.LogMessage(message); //AWS =&amp;gt; User created Successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add another function to the delegate, just assign it as a concatenation item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myLogger.Log +=  (message) =&amp;gt; 
{ 
    // File.Write....
    Console.WriteLine($"File =&amp;gt; {message}");
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final code with all possible Loggers and MyLogger class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public delegate void LogHandler(string message);

public class MyLogger
{
    public LogHandler Log;

    public void LogMessage(string message)
    {
        Log?.Invoke(message);
    }
}

public void CreateUser()
{
    // Create User logic...
    // User created
    var message = "User created Successfully";

    var myLogger = new MyLogger();

    myLogger.Log +=  (message) =&amp;gt; 
    { 
        // Send to AWS Cloud....
        Console.WriteLine($"AWS =&amp;gt; {message}");
    };

    myLogger.Log +=  (message) =&amp;gt; 
    { 
        // File.Write....
        Console.WriteLine($"File =&amp;gt; {message}");
    };

    myLogger.Log +=  (message) =&amp;gt; 
    { 
        // Send to Azure Cloud....
        Console.WriteLine($"Azure =&amp;gt; {message}");
    };

    myLogger.Log +=  (message) =&amp;gt; 
    { 
        // Send to Elasticsearch....
        Console.WriteLine($"Elasticsearch =&amp;gt; {message}");
    };

    // Execute Delegate
    myLogger.LogMessage(message);

    //AWS =&amp;gt; User created Successfully
    //File =&amp;gt; User created Successfully
    //Azure =&amp;gt; User created Successfully
    //Elasticsearch =&amp;gt; User created Successfully
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I expect you got the idea and have learned the basics about delegates and more important, in which scenarios you can implement them.&lt;/p&gt;

&lt;p&gt;So, Thanks for reading and keep learning =)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
