<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Full Stack Content Creator on Medium]]></title>
        <description><![CDATA[Stories by Full Stack Content Creator on Medium]]></description>
        <link>https://medium.com/@javvadirupasri8?source=rss-dab3141711d6------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*gDu_dEEjADM_gN42AVeNOw.jpeg</url>
            <title>Stories by Full Stack Content Creator on Medium</title>
            <link>https://medium.com/@javvadirupasri8?source=rss-dab3141711d6------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 27 May 2026 23:36:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@javvadirupasri8/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[10 Effective Tips for Healthy Weight Gain]]></title>
            <link>https://mobileappcircular.com/10-effective-tips-for-healthy-weight-gain-69af49a57f79?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/69af49a57f79</guid>
            <category><![CDATA[health]]></category>
            <category><![CDATA[weight-gain]]></category>
            <category><![CDATA[healthy-lifestyle]]></category>
            <category><![CDATA[life]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Thu, 26 Sep 2024 07:40:18 GMT</pubDate>
            <atom:updated>2024-09-26T07:40:18.990Z</atom:updated>
            <content:encoded><![CDATA[<p>For many, the challenge isn’t about losing weight but gaining it in a healthy and sustainable way. Whether your goal is to build muscle, increase your energy levels, or improve overall body mass, the key to gaining weight is following a balanced approach. Here are 10 proven tips for healthy weight gain.</p><p>1. Increase Caloric Intake</p><p>To gain weight, you need to consume more calories than you burn. This doesn’t mean filling up on junk food, but rather adding nutrient-dense foods to your diet. Calculate your daily caloric needs and aim to consume 300-500 calories above that.</p><p>Tip: Include calorie-dense foods like nuts, seeds, avocados, and whole grains to your meals.</p><p>2. Eat More Protein</p><p>Protein is essential for muscle growth and repair. When trying to gain weight, aim for 1.5 to 2 grams of protein per kilogram of body weight. Foods like lean meats, fish, eggs, dairy, and plant-based options like lentils, chickpeas, and tofu are great sources of protein.</p><p>Tip: Incorporate protein shakes or smoothies between meals for an easy protein boost.</p><p>3. Have Frequent Meals</p><p>If your appetite is small, it might be hard to eat large portions in one sitting. Instead, aim for 5-6 smaller meals throughout the day. This makes it easier to increase your overall calorie intake without feeling too full or bloated.</p><p>Tip: Set reminders to eat every 2-3 hours to stay consistent.</p><p>4. Consume Healthy Fats</p><p>Fat is more calorie-dense than protein or carbohydrates, making it an efficient way to increase caloric intake. Focus on consuming healthy fats from sources like olive oil, avocados, nuts, seeds, and fatty fish.</p><p>Tip: Drizzle olive oil on your salads or stir some peanut butter into your smoothie for a quick caloric boost.</p><p>5. Lift Weights</p><p>If your goal is to gain muscle weight, strength training is essential. Compound exercises like squats, deadlifts, bench presses, and rows engage multiple muscle groups, promoting overall muscle growth.</p><p>Tip: Aim to lift weights 3-4 times per week, progressively increasing the weight as you get stronger.</p><p>6. Drink Your Calories</p><p>If you struggle to meet your calorie goals through solid foods alone, liquid calories are a great option. Smoothies, protein shakes, and full-fat dairy are nutrient-dense and easy to consume.</p><p>Tip: Make a high-calorie smoothie with bananas, almond butter, oats, protein powder, and whole milk for a calorie-packed snack.</p><p>7. Choose Nutrient-Dense Foods</p><p>Avoid relying on junk food or sugary treats to gain weight, as this can lead to unhealthy fat gain. Instead, focus on nutrient-dense foods that provide vitamins, minerals, and energy.</p><p>Tip: Whole foods like potatoes, brown rice, quinoa, lean meats, and leafy greens should form the base of your diet.</p><p>8. Add Extras to Every Meal</p><p>Simple additions to your meals can help pack in extra calories. Add grated cheese to your pasta, spread butter on toast, or stir nuts and seeds into yogurt.</p><p>Tip: Top your meals with avocado or drizzle a little extra oil to increase the calorie content without changing the flavor too much.</p><p>9. Stay Hydrated, But Don’t Overdo It</p><p>Drinking too much water right before or during meals can fill you up, leaving less room for food. It’s important to stay hydrated, but sip water between meals to avoid suppressing your appetite.</p><p>Tip: Opt for drinks with calories, like fruit juice or milk, alongside meals.</p><p>10. Get Enough Sleep</p><p>Sleep is crucial for recovery and muscle growth, especially if you are working out regularly. Lack of sleep can hinder your ability to gain weight by slowing down recovery and reducing energy levels.</p><p>Tip: Aim for at least 7-9 hours of sleep each night to support muscle growth and overall health.</p><p>Conclusion</p><p>Gaining weight requires consistency, patience, and a balanced approach. By focusing on nutrient-dense foods, regular strength training, and small adjustments to your daily routine, you can achieve your weight gain goals in a healthy and sustainable way. Remember, it’s not just about increasing calories but also nourishing your body with the right nutrients to support long-term health.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=69af49a57f79" width="1" height="1" alt=""><hr><p><a href="https://mobileappcircular.com/10-effective-tips-for-healthy-weight-gain-69af49a57f79">10 Effective Tips for Healthy Weight Gain</a> was originally published in <a href="https://mobileappcircular.com">Mobile App Circular</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Beginner’s Guide to Dependency Injection in .NET Core]]></title>
            <link>https://medium.com/@javvadirupasri8/a-beginners-guide-to-dependency-injection-in-net-core-4bbc1df37253?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/4bbc1df37253</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Tue, 24 Sep 2024 12:56:48 GMT</pubDate>
            <atom:updated>2024-09-24T12:56:48.079Z</atom:updated>
            <content:encoded><![CDATA[<p>Dependency injection is a design pattern that has become an essential part of modern software development. In .NET Core, it is built into the framework, providing a simple and powerful way to manage object dependencies and achieve loose coupling between components.</p><p>If you’re new to .NET Core or dependency injection, this guide will help you get started. We’ll cover the basics of dependency injection and show you how to use it in your .NET Core applications.</p><h4>What is Dependency Injection?</h4><p>Dependency injection is a software design pattern that allows you to separate the construction and use of objects. Instead of creating objects directly, you define the dependencies of a class or component and let the container inject the dependencies at runtime.</p><p><strong>This approach has several benefits:</strong></p><ul><li>Loose coupling: Dependencies are not hardcoded, so components can be easily replaced or modified.</li><li>Testability: Dependencies can be easily mocked or substituted during unit testing.</li><li>Flexibility: Components can be easily configured and customized at runtime.</li></ul><h4>How Does Dependency Injection Work in .NET Core?</h4><p>.NET Core provides a built-in dependency injection container that can be used to register and resolve dependencies. Here’s how it works:</p><ol><li>Define Interfaces and Classes</li></ol><p>The first step is to define interfaces for the services or components that you want to use in your application. Then, you implement these interfaces with concrete classes that provide the actual implementation of the services.</p><p>For example:</p><pre>// Interface for a service<br>public interface IMyService<br>{<br>    void DoSomething();<br>}<br><br>// Implementation of the service<br>public class MyService : IMyService<br>{<br>    public void DoSomething()<br>    {<br>        // Implementation<br>    }<br>}</pre><p>2. Register Services</p><p>Next, you register your services with the DI container during application startup. This is typically done in the ConfigureServices method in the Startup class.</p><p>For example:</p><pre>public void ConfigureServices(IServiceCollection services)<br>{<br>    // Register a service with its implementation<br>    services.AddScoped&lt;IMyService, MyService&gt;();<br>}</pre><p>3. Resolve Dependencies</p><p>Now, you can use the registered services in your application by injecting them into the constructor or method of the dependent classes. The DI container will automatically resolve and provide the appropriate implementation for the registered services.</p><p>For example:</p><pre>public class MyController : Controller<br>{<br>    private readonly IMyService _myService;<br><br>    public MyController(IMyService myService)<br>    {<br>        _myService = myService;<br>    }<br><br>    // Use the registered service in the controller action<br>    public IActionResult Index()<br>    {<br>        _myService.DoSomething();<br>        return View();<br>    }<br>}</pre><p>4. Lifetime Management</p><p>.NET Core provides different options for managing the lifetime of registered services, such as AddTransient, AddScoped, and AddSingleton. These options control how the DI container creates and manages instances of the registered services, depending on your application&#39;s requirements.</p><p>For example:</p><pre>// Add a transient service<br>services.AddTransient&lt;IMyService, MyService&gt;();<br><br>// Add a scoped service<br>services.AddScoped&lt;IMyService, MyService&gt;();<br><br>// Add a singleton service<br>services.AddSingleton&lt;IMyService, MyService&gt;();</pre><h4>Conclusion</h4><p>Dependency injection is a powerful tool for managing object dependencies and achieving loose coupling between components in .NET Core applications. By using the built-in DI container, you can easily register and resolve dependencies and improve the testability, maintainability, and extensibility of your code.</p><p>In this guide, we’ve covered the basics of dependency injection in .NET Core. With a solid understanding of the fundamentals, you’ll be well on your way to building more robust and scalable applications with .NET Core.</p><p>Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4bbc1df37253" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Decoding JavaScript Hoisting: A Must-Know Concept for Interviews]]></title>
            <link>https://medium.com/@javvadirupasri8/decoding-javascript-hoisting-a-must-know-concept-for-interviews-c4e23438e93e?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/c4e23438e93e</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Sun, 10 Sep 2023 07:56:52 GMT</pubDate>
            <atom:updated>2023-09-10T07:56:52.431Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*opP6MseQGk9QHO_zLiRgig.png" /></figure><p>In JavaScript, “hoisting” refers to the process by which <em>variable and function declarations are moved to the top of their respective scopes during the compilation phase</em>, before the code is actually executed.</p><p>This means that you can use variables and functions in your code before they are actually declared, as long as they are declared within the same scope. However, it’s important to understand how hoisting works in order to avoid any unexpected behavior.</p><p>Here are some examples of hoisting in JavaScript:</p><p>Example 1: <strong>Variable Hoisting</strong></p><p>Variable hoisting refers to the behavior where JavaScript variables are moved to the top of their containing scope during the compilation phase, allowing them to be accessed before their actual declaration in the code. However, only the variable declaration (not the assignment) is hoisted.</p><p>Let’s take a look at an example:</p><pre>console.log(x); // Output: undefined<br>var x = 5;</pre><p>In this example, even though x is logged before it&#39;s actually declared and assigned a value, the code doesn&#39;t throw an error. This is because the declaration of x is hoisted to the top of the scope (global or function scope), but the assignment of the value 5 to x happens later in the code. When console.log(x) is executed, x has been declared but not yet assigned a value, so its value is undefined.</p><p>Example 2: <strong>Function Hoisting</strong></p><p>Function hoisting is similar to variable hoisting, but applies to function declarations. Function declarations are moved to the top of their containing scope during the compilation phase, allowing them to be called before their actual declaration in the code.</p><p>Let’s take a look at an example:</p><pre>hello(); // Output: &quot;Hello, world!&quot;<br>function hello() {<br>  console.log(&quot;Hello, world!&quot;);<br>}</pre><p>In this example, the function hello() is called before it&#39;s actually declared. However, the code doesn&#39;t throw an error because the function declaration is hoisted to the top of the scope. So, when hello() is called, the function has already been declared and can be executed, resulting in the output &quot;Hello, world!&quot;.</p><p>Example 3: <strong>Function Expression Hoisting<br></strong>Function expression hoisting is different from function declaration hoisting. In JavaScript, function expressions are not hoisted to the top of their containing scope during the compilation phase like function declarations. Instead, they behave like regular variable declarations and are subject to variable hoisting.</p><p>Let’s take a look at an example:</p><pre>hello(); // Output: TypeError: hello is not a function<br>var hello = function() {<br>  console.log(&quot;Hello, world!&quot;);<br>};</pre><p>In this example, we’re using a function expression to assign a function to a variable hello. However, when we try to call hello() before it&#39;s actually declared and assigned, we get a TypeError. This is because function expressions are not hoisted in the same way as function declarations. In this case, the variable hello is hoisted to the top of the scope with an initial value of undefined, and at the time of the function call, it&#39;s still undefined, resulting in the error.</p><p>Example 4: <strong>Hoisting in Nested Functions</strong></p><p>Hoisting in nested functions refers to how hoisting works when functions are declared inside other functions.</p><p>Let’s take a look at an example:</p><pre>function greet() {<br>  console.log(&quot;Hello!&quot;);<br><br>  function sayName() { // Nested function declaration (hoisted)<br>    console.log(&quot;My name is John.&quot;);<br>  }<br><br>  sayName();<br>}<br><br>greet();<br></pre><p>In this example, we have a function greet that contains a nested function declaration sayName. When the greet function is called, it logs &quot;Hello!&quot; to the console, and then calls the sayName function. Even though the sayName function is declared inside the greet function, it is hoisted to the top of the greet function during the compilation phase, allowing it to be called before its actual declaration.</p><p>This will output:</p><pre>Hello!<br>My name is John.</pre><p>This is because the nested function sayName is hoisted to the top of the greet function, allowing it to be called after the &quot;Hello!&quot; message is logged.<br><strong>Note</strong>:It’s important to note that hoisting in nested functions only occurs within the containing function’s scope. Nested functions are not hoisted to the global scope or to outer function scopes.</p><h4>Best Practices:</h4><p>To avoid unexpected behavior due to hoisting, it’s recommended to always declare and initialize variables before using them. It’s also good practice to place function declarations before calling them in your code to ensure they are properly hoisted. Additionally, be aware of the differences between function declarations and function expressions in terms of hoisting behavior.</p><h4>Conclusion:</h4><p>In conclusion, hoisting is a unique feature of JavaScript that allows variable and function declarations to be moved to the top of their respective scopes during the compilation phase. It enables you to use variables and functions before they are actually declared, but it’s important to understand how hoisting works to avoid unexpected behavior.</p><p>I hope this detailed blog post on Hoisting in javascript with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding.</p><p>Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c4e23438e93e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Demystifying Static in C#: Understanding How it Works]]></title>
            <link>https://medium.com/@javvadirupasri8/demystifying-static-in-c-understanding-how-it-works-d7b47a1acb32?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/d7b47a1acb32</guid>
            <category><![CDATA[development]]></category>
            <category><![CDATA[oop]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[dotnet-core]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Thu, 18 May 2023 17:23:23 GMT</pubDate>
            <atom:updated>2023-05-18T17:23:23.341Z</atom:updated>
            <content:encoded><![CDATA[<p>In object-oriented programming languages like C#, the “static” keyword can sometimes be confusing for developers, especially those who are new to the language. Static is a modifier that can be applied to fields, methods, properties, events, and nested classes in C#, and it changes their behavior in significant ways. In this article, we will demystify static in C# and explore how it works.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/519/1*uMZZDOnfkqcptjYwT_diVA.png" /></figure><h4>What is Static?</h4><p>In C#, static is used to define members that belong to a type rather than an instance of the type. This means that a static member is shared among all instances of a class, rather than being unique to each instance. When a member is marked as static, it can be accessed without creating an instance of the class.</p><h4>Static Fields and Properties</h4><p>Static fields and properties are shared among all instances of a class. They are initialized only once, when the type is first accessed, and their values are preserved across multiple instances of the class. Static fields and properties are declared using the static keyword before the field or property declaration.</p><p>Here’s an example of a static field and property in C#:</p><pre>class MyClass<br>{<br>    public static int staticField = 10; // Static field<br>    public static int StaticProperty { get; set; } // Static property<br>}</pre><p>In the above example, staticField is a static field, and StaticProperty is a static property. These members can be accessed without creating an instance of the MyClass class, like this:</p><pre>int fieldValue = MyClass.staticField; // Accessing static field<br>int propertyValue = MyClass.StaticProperty; // Accessing static property<br><br>MyClass.staticField = 20; // Modifying static field<br>MyClass.StaticProperty = 30; // Modifying static property</pre><h4>Static Methods</h4><p>Static methods are methods that can be called without creating an instance of a class. They can only access static members of the class and cannot access non-static (instance) members directly. Static methods are declared using the static keyword before the method declaration.</p><p>Here’s an example of a static method in C#:</p><pre>class MyClass<br>{<br>    public static void StaticMethod()<br>    {<br>        // Code for static method<br>    }<br>}</pre><p>In the above example, StaticMethod is a static method that can be called without creating an instance of the MyClass class, like this:</p><pre>MyClass.StaticMethod(); // Calling static method</pre><h4>Static Classes</h4><p>In C#, a class can also be marked as static, which means that it cannot be instantiated, and all its members must be static. A static class is sealed and cannot be used as a base class or have instance members.</p><p>Here’s an example of a static class in C#:</p><pre>static class MyStaticClass<br>{<br>    public static void StaticMethod()<br>    {<br>        // Code for static method in a static class<br>    }<br>}</pre><p>In the above example, MyStaticClass is a static class that contains only static members. The static members of a static class can be accessed without creating an instance of the class, like this:</p><pre>MyStaticClass.StaticMethod(); // Calling static method in a static class</pre><h4>Static constructor</h4><p>A static constructor is a special constructor that is automatically called by the runtime before any static members of a class are accessed or any static methods are called. It is used to perform initialization tasks that are specific to the type itself, rather than to any specific instance of the type.</p><p>Here’s an example of a static constructor:</p><pre>public class Logger<br>{<br>    // Static field<br>    private static string logFile;<br><br>    // Static constructor<br>    static Logger()<br>    {<br>        // Initialization code<br>        logFile = &quot;log.txt&quot;;<br>        InitializeLogFile();<br>    }<br><br>    // Static method<br>    public static void Log(string message)<br>    {<br>        // Log the message to the log file<br>        // ...<br>    }<br><br>    // Private static method<br>    private static void InitializeLogFile()<br>    {<br>        // Code to initialize the log file<br>        // ...<br>    }<br>}<br><br>// Calling static method<br>Logger.Log(&quot;Error occurred: ...&quot;);</pre><p>In this example, we have a static constructor in the “Logger” class that is defined using the static keyword and has the same name as the class. The static constructor is automatically called by the runtime before any static members are accessed or any static methods are called. Inside the static constructor, we can perform initialization tasks that are specific to the type, such as initializing static fields or calling static methods.</p><p>Static constructors are useful when we need to perform one-time setup operations that are specific to the type, such as initializing static fields, opening connections, or loading configuration data. They are only executed once per application domain, regardless of the number of instances created for the type. It’s important to note that we cannot explicitly call a static constructor in C#; it is automatically called by the runtime.</p><h4>Key Points to Remember</h4><ul><li>Static members in C# are shared among all instances of a class and can be accessed without creating an instance of the class.</li><li>Static fields and properties are initialized only once, when the type is first accessed, and their values are preserved across multiple instances of the class.</li><li>Static methods can only access static members of the class and cannot access non-static (instance) members directly.</li><li>Static classes are sealed and cannot be instantiated, and all their members must be static.</li><li>Static members are accessed using the class name followed by the member name, without creating an instance of the class.</li><li>Static members are useful for maintaining shared data or behavior that needs to be accessible across instances of a class or for utility methods that do not require instance-specific data.</li><li>However, the use of static members should be carefully considered, as they can introduce potential issues such as global state and tight coupling between components.</li></ul><h4>Best Practices for Using Static in C#</h4><ol><li><strong>Use static members sparingly:</strong> Static members should be used judiciously and only for scenarios where shared data or behavior is truly required across instances of a class. Overuse of static members can lead to global state and make code difficult to maintain and test.</li><li><strong>Be mindful of thread safety:</strong> Static members are shared among all instances of a class and can be accessed concurrently by multiple threads. Therefore, it’s important to ensure proper synchronization when accessing and modifying static members in multi-threaded environments to avoid race conditions and other concurrency issues.</li><li><strong>Avoid static mutable state:</strong> Static fields that can be modified should be used with caution, as they can introduce hidden dependencies and make code harder to reason about. Prefer immutable static fields or static properties with read-only access.</li><li><strong>Prefer instance members for instance-specific data: </strong>If data or behavior is specific to an instance of a class, it’s usually better to use instance members rather than static members. Instance members encapsulate data within the instance, making it easier to reason about and manage the lifecycle of the data.</li><li><strong>Use static classes for utility methods: </strong>Static classes with static methods can be useful for utility methods that do not require any instance-specific data. For example, helper methods for string manipulation or mathematical calculations can be implemented as static methods in a static class.</li><li><strong>Follow naming conventions: </strong>By convention, static members are typically named using PascalCase with the first letter capitalized, and the static keyword is used as a prefix. This makes it clear that the member is static and not an instance member.</li></ol><p>Let’s take a real-time example to illustrate the use of static in C#. Let’s say we have a class called “MathUtility” that contains utility methods for performing mathematical calculations. These utility methods do not require any instance-specific data and can be shared across all instances of the class.</p><pre>public class MathUtility<br>{<br>    // Static field<br>    public static double PI = 3.14159;<br><br>    // Static method to calculate the area of a circle<br>    public static double CalculateAreaOfCircle(double radius)<br>    {<br>        return PI * radius * radius;<br>    }<br><br>    // Static method to calculate the square root of a number<br>    public static double CalculateSquareRoot(double number)<br>    {<br>        return Math.Sqrt(number);<br>    }<br>}</pre><p>In this example, we have a static field “PI” that stores the value of pi, which is shared among all instances of the class. We also have two static methods, “CalculateAreaOfCircle” and “CalculateSquareRoot”, that perform mathematical calculations and do not require any instance-specific data.</p><p>Now, we can use the static members of the “MathUtility” class without creating an instance of the class:</p><pre>// Accessing static field<br>double piValue = MathUtility.PI;<br><br>// Calling static methods<br>double radius = 5;<br>double area = MathUtility.CalculateAreaOfCircle(radius);<br>double squareRoot = MathUtility.CalculateSquareRoot(25);<br></pre><p>As you can see, we can access the static field “PI” and call the static methods “CalculateAreaOfCircle” and “CalculateSquareRoot” directly using the class name followed by the member name, without creating an instance of the “MathUtility” class. This allows us to use the utility methods and shared data across different parts of our code without having to create multiple instances of the class.</p><h4><strong>Order of execution </strong>for static members (fields, properties, constructors, and methods) and classes follows a specific flow:</h4><ol><li><strong>Static fields and properties</strong>: Static fields and properties are initialized in the order they are declared within the class, and before any static constructors or methods are called. If static fields or properties depend on each other, their initialization order matters, and it’s important to be aware of potential dependencies and ensure they are properly initialized.</li><li><strong>Static constructor:</strong> The static constructor (also known as the type initializer) is called automatically by the runtime before any static members are accessed or any static methods are called, and it’s guaranteed to execute only once per application domain. The static constructor is used to initialize static members or perform any other setup that needs to be done before static members are used.</li><li><strong>Static methods:</strong> Static methods can be called after static fields, properties, and the static constructor are initialized. They can be called directly using the class name followed by the method name, without creating an instance of the class.</li><li><strong>Class initialization: </strong>Once the static fields, properties, and constructor have been executed, the class is considered to be fully initialized and ready for use. At this point, the class is considered “live” and its static members can be accessed and used.</li><li><strong>Instance members:</strong> Instance members (fields, properties, constructors, and methods) are associated with specific instances of a class and can only be accessed after an instance of the class has been created using the “new” keyword. Instance members are <strong>not related to the static members </strong>in terms of their order of execution.</li></ol><p>It’s important to note that static members are associated with the type itself, rather than with any specific instance of the type. They are shared among all instances of the class and can be accessed independently of any specific instance. The order of execution for static members and classes is deterministic and follows the flow mentioned above, ensuring that static members are properly initialized before they are used in C# code.</p><p><strong>Note</strong>: It’s important to use static members judiciously and follow best practices to ensure proper synchronization, mutability, and naming conventions.</p><h4>Conclusion</h4><p>Static members in C# provide a way to define shared data or behavior that is accessible without creating an instance of a class. However, they should be used with caution and only in scenarios where shared data or behavior is truly required. Careful consideration should be given to thread safety, mutability, and naming conventions when using static members in C# code. By following best practices and understanding how static works in C#, developers can effectively utilize this powerful feature to write efficient and maintainable code.</p><p>I hope this detailed blog post on Static in C# with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding. Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d7b47a1acb32" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Method Hiding, Shadowing, and Overriding in C# Explained with Examples]]></title>
            <link>https://medium.com/@javvadirupasri8/method-hiding-shadowing-and-overriding-in-c-explained-with-examples-643c7dfc8ccc?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/643c7dfc8ccc</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[design]]></category>
            <category><![CDATA[oops-interview-questions]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Wed, 10 May 2023 18:59:46 GMT</pubDate>
            <atom:updated>2023-05-10T18:59:46.726Z</atom:updated>
            <content:encoded><![CDATA[<p>Method hiding, shadowing, and overriding are important concepts in object-oriented programming using C#.</p><p>They involve the use of virtual, override, and new keywords to define and implement methods in derived classes that are related to methods in base classes. In this blog post, we will explore these concepts in detail and provide examples to illustrate how they work in C#.</p><h4>Method Hiding:</h4><ul><li>Method hiding is a concept where a derived class defines a new method with the same name as a method in the base class, effectively hiding the base class method.</li><li>Method hiding is achieved by using the new keyword in the derived class method.</li><li>The base class method should be marked as virtual to be hidden by the derived class method.</li><li>The derived class method must have the same name as the base class method, but it can have a different return type or method signature.</li><li>Example:</li></ul><pre>public class Animal<br>{<br>    public virtual void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Animal makes a sound.&quot;);<br>    }<br>}<br><br>public class Cat : Animal<br>{<br>    public new void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Cat makes a sound.&quot;);<br>    }<br>}<br><br>public class Program<br>{<br>    static void Main()<br>    {<br>       // Method Hiding<br>        Animal animal1 = new Animal();<br>        Animal cat1 = new Cat();<br>        Cat animal2 = new Animal(); // Compilation error - cannot implicitly convert Animal to Cat<br>        Cat cat2 = new Cat();<br>        <br>        animal1.MakeSound(); // Output: &quot;Animal makes a sound.&quot;<br>        cat1.MakeSound();    // Output: &quot;Animal makes a sound.&quot; (hiding)<br>        cat2.MakeSound();    // Output: &quot;Cat makes a sound.&quot;<br>    }<br>}</pre><h4>Method Shadowing:</h4><ul><li>Method shadowing is similar to method hiding, where a derived class defines a new method with the same name as a method in the base class.</li><li>However, in method shadowing, the base class method is not marked as virtual , and the derived class method does not use the new keyword.</li><li>This can lead to unexpected behavior as the base class method may still be invoked when calling the method on an object of the derived class.</li><li>Example:</li></ul><pre>public class Animal<br>{<br>    public void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Animal makes a sound.&quot;);<br>    }<br>}<br><br>public class Cat : Animal<br>{<br>    public void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Cat makes a sound.&quot;);<br>    }<br>}<br><br>public class Program<br>{<br>    static void Main()<br>    {<br>        // Method Shadowing<br>        Animal animal1 = new Animal();<br>        Animal cat1 = new Cat();<br>        Cat animal2 = new Animal(); // Compilation error - cannot implicitly convert Animal to Cat<br>        Cat cat2 = new Cat();<br>        <br>        animal1.MakeSound(); // Output: &quot;Animal makes a sound.&quot;<br>        cat1.MakeSound();    // Output: &quot;Animal makes a sound.&quot; (shadowing)<br>        cat2.MakeSound();    // Output: &quot;Cat makes a sound.&quot;  <br>    }<br>}</pre><h4>Method Overriding:</h4><ul><li>Method overriding is a concept where a derived class provides a new implementation of a base class method, and the new implementation is used when calling the method on an object of the derived class.</li><li>Method overriding is achieved by using the override keyword in the derived class method.</li><li>The base class method should be marked as virtual and the derived class method must have the same name, return type, and method signature.</li><li>Example:</li></ul><pre>public class Animal<br>{<br>    public virtual void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Animal makes a sound.&quot;);<br>    }<br>}<br><br>public class Cat : Animal<br>{<br>    public override void MakeSound()<br>    {<br>        Console.WriteLine(&quot;Cat makes a sound.&quot;);<br>    }<br>}<br><br>public class Program<br>{<br>    static void Main()<br>    {<br>        // Method Overriding<br>        Animal animal1 = new Animal();<br>        Cat animal2 = new Animal(); // Compilation error - cannot implicitly convert Animal to Cat<br>        Animal cat1 = new Cat();<br>        Cat cat2 = new Cat();<br>        <br>        animal1.MakeSound(); // Output: &quot;Animal makes a sound.&quot;<br>        cat1.MakeSound();    // Output: &quot;Cat makes a sound.&quot; (overriding)<br>        cat2.MakeSound();    // Output: &quot;Cat makes a sound.&quot;<br>    }<br>}</pre><h4>Differences between Method Hiding, Shadowing, and Overriding:</h4><ol><li><strong>Method Hiding</strong>:</li></ol><ul><li>Derived class defines a new method with the same name as a method in the base class, effectively hiding the base class method.</li><li>new keyword is used in the derived class method.</li><li>Base class method should be marked as virtual or override.</li><li>Derived class method can have a different return type or method signature.</li></ul><p><strong>2. Method Shadowing</strong>:</p><ul><li>Derived class defines a new method with the same name as a method in the base class, but the base class method is <strong>not marked</strong> as virtual or override.</li><li>Base class method may still be invoked when calling the method on an object of the derived class.</li><li>No new keyword is used in the derived class method.</li></ul><p><strong>3. Method Overriding:</strong></p><ul><li>Derived class provides a new implementation of a base class method.</li><li>override keyword is used in the derived class method.</li><li>Base class method should be marked as virtual, abstract, or override.</li><li>Derived class method must have the same name, return type, and method signature as the base class method.</li></ul><p>In conclusion, method hiding, shadowing, and overriding are important concepts in C# that allow for customization and extension of base class methods in derived classes. By following the proper guidelines for creating objects and implementing these concepts, you can ensure correct and expected behavior in your object-oriented programming code.</p><p>I hope this detailed blog post on Method hiding, shadowing and overriding in C# with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding. Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=643c7dfc8ccc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Angular Lifecycle Hooks: A Comprehensive Guide]]></title>
            <link>https://towardsdev.com/understanding-angular-lifecycle-hooks-a-comprehensive-guide-52f5123f083?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/52f5123f083</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Tue, 02 May 2023 17:35:30 GMT</pubDate>
            <atom:updated>2023-05-04T10:14:17.177Z</atom:updated>
            <content:encoded><![CDATA[<p>Introduction</p><p>Angular is a popular framework for building web applications, and it comes with a rich set of features, including lifecycle hooks. Lifecycle hooks are special methods provided by Angular that allow you to tap into different stages of a component’s lifecycle and perform actions accordingly. Understanding lifecycle hooks is essential for properly managing component behavior, handling data, and optimizing performance in Angular applications.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*TWzN_0m1pnRNv0pSyXuW3Q.png" /><figcaption>Component LifeCycle Hooks</figcaption></figure><p>In this blog post, we will explore the different types of lifecycle hooks in Angular, their order of execution, and how to use them effectively in real-world scenarios. We will provide clear explanations and examples to help you grasp the concepts easily.</p><p>Types of Angular Lifecycle Hooks: Angular provides several types of lifecycle hooks that can be categorized into three main groups:</p><h4>Component Lifecycle Hooks:</h4><p>These hooks are specific to components and are executed during different stages of a component’s lifecycle. They allow you to perform actions before, after, or during specific lifecycle events, such as component creation, content initialization, content checking, and content destruction.</p><ul><li>ngOnInit(): This hook is called after the component has been initialized and its inputs have been set. It is commonly used for component initialization tasks, such as fetching data from APIs, setting up subscriptions, and initializing component properties.</li><li>ngOnChanges(changes: SimpleChanges): This hook is called whenever the value of one of the component’s input properties changes. It provides you with the previous and current values of the input property, allowing you to respond to input changes and update the component accordingly.</li><li>ngDoCheck(): This hook is called during every change detection cycle, which is triggered by Angular’s change detection mechanism. It allows you to perform custom change detection logic and optimize component performance.</li><li>ngAfterContentInit(): This hook is called after content (e.g., child components, projected content) has been initialized in the component’s view. It is commonly used for actions that need to be performed after content initialization, such as manipulating the DOM or setting up third-party libraries.</li><li>ngAfterContentChecked(): This hook is called after content has been checked for changes. It is commonly used for actions that need to be performed after content checking, such as updating component state or triggering change detection manually.</li><li>ngAfterViewInit(): This hook is called after the component’s view has been initialized. It is commonly used for actions that need to be performed after view initialization, such as accessing DOM elements or setting up view-related logic.</li><li>ngAfterViewChecked(): This hook is called after the component’s view has been checked for changes. It is commonly used for actions that need to be performed after view checking, such as updating component state or triggering change detection manually.</li><li>ngOnDestroy(): This hook is called just before the component is destroyed. It is commonly used for cleanup tasks, such as unsubscribing from subscriptions, releasing resources, or tearing down third-party libraries.</li></ul><h4>Directive Lifecycle Hooks:</h4><p>These hooks are specific to directives and are executed during different stages of a directive’s lifecycle. They are similar to component lifecycle hooks, but they apply to directives instead of components.</p><h4>Module Lifecycle Hooks:</h4><p>These hooks are specific to modules and are executed during different stages of a module’s lifecycle. They allow you to perform actions before, after, or during specific module events, such as module instantiation, module destruction, or module configuration.</p><h4>Order of Execution:</h4><p>The lifecycle hooks in Angular are executed in a specific order, forming a lifecycle sequence for components and directives. Understanding the order of execution is crucial for properly managing component behavior and avoiding unexpected results.</p><p>The typical order of execution for component lifecycle hooks is as follows:</p><ol><li>ngOnChanges()</li><li>ngOnInit()</li><li>ngDoCheck()</li><li>ngAfterContentInit()</li><li>ngAfterContentChecked()</li><li>ngAfterViewInit()</li><li>ngAfterViewChecked()</li><li>ngOnDestroy()</li></ol><p>It’s important to note that not all hooks are always called during every lifecycle event. For example, ngOnChanges() is only called when an input property changes, while ngOnDestroy() is only called when the component is about to be destroyed. Understanding when and how each hook is called is crucial for leveraging their functionalities effectively in your Angular application.</p><h4>Real-time Scenarios:</h4><p>Let’s explore some real-time scenarios where lifecycle hooks can be useful in Angular applications:</p><ol><li>Fetching Data from APIs: You can use the ngOnInit() hook to fetch data from APIs and initialize component properties with the retrieved data. This ensures that the data is available when the component is rendered in the view, avoiding any potential race conditions or data inconsistencies.</li></ol><pre>import { Component, OnInit } from &#39;@angular/core&#39;;<br>import { DataService } from &#39;app/services/data.service&#39;;<br><br>@Component({<br>  selector: &#39;app-user&#39;,<br>  templateUrl: &#39;./user.component.html&#39;,<br>  styleUrls: [&#39;./user.component.css&#39;]<br>})<br>export class UserComponent implements OnInit {<br>  users: any[];<br><br>  constructor(private dataService: DataService) { }<br><br>  ngOnInit() {<br>    this.dataService.getUsers().subscribe(data =&gt; {<br>      this.users = data;<br>    });<br>  }<br>}</pre><p>2. DOM Manipulation: You can use the ngAfterViewInit() hook to access DOM elements and perform DOM manipulation tasks, such as setting focus, updating styles, or initializing third-party libraries. This ensures that the DOM elements are fully rendered and available for manipulation.</p><p>Example:</p><pre>import { Component, AfterViewInit, ElementRef } from &#39;@angular/core&#39;;<br><br>@Component({<br>  selector: &#39;app-custom-input&#39;,<br>  templateUrl: &#39;./custom-input.component.html&#39;,<br>  styleUrls: [&#39;./custom-input.component.css&#39;]<br>})<br>export class CustomInputComponent implements AfterViewInit {<br>  constructor(private elementRef: ElementRef) { }<br><br>  ngAfterViewInit() {<br>    // Accessing DOM element and setting focus<br>    this.elementRef.nativeElement.querySelector(&#39;input&#39;).focus();<br>  }<br>}</pre><p>3. Cleanup Tasks: You can use the ngOnDestroy() hook to perform cleanup tasks, such as unsubscribing from subscriptions, releasing resources, or tearing down third-party libraries. This ensures that the component is properly cleaned up before it is destroyed, avoiding any memory leaks or performance issues.</p><p>Example:</p><pre>import { Component, OnDestroy } from &#39;@angular/core&#39;;<br>import { Subscription } from &#39;rxjs&#39;;<br>import { DataService } from &#39;app/services/data.service&#39;;<br><br>@Component({<br>  selector: &#39;app-dashboard&#39;,<br>  templateUrl: &#39;./dashboard.component.html&#39;,<br>  styleUrls: [&#39;./dashboard.component.css&#39;]<br>})<br>export class DashboardComponent implements OnDestroy {<br>  data: any[];<br>  dataSubscription: Subscription;<br><br>  constructor(private dataService: DataService) {<br>    this.dataSubscription = this.dataService.getData().subscribe(data =&gt; {<br>      this.data = data;<br>    });<br>  }<br><br>  ngOnDestroy() {<br>    // Unsubscribing from the subscription to avoid memory leaks<br>    this.dataSubscription.unsubscribe();<br>  }<br>}</pre><h4>Conclusion:</h4><p>Lifecycle hooks are a powerful feature in Angular that allow you to perform actions at different stages of a component or directive’s lifecycle. By understanding the different types of hooks, their order of execution, and how to use them effectively in real-time scenarios, you can better manage component behavior, handle data, and optimize performance in your Angular applications.</p><p>We hope this comprehensive guide has provided you with a clear understanding of Angular lifecycle hooks and how to leverage their functionalities in your projects.</p><p>Happy coding!<br>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=52f5123f083" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/understanding-angular-lifecycle-hooks-a-comprehensive-guide-52f5123f083">Understanding Angular Lifecycle Hooks: A Comprehensive Guide</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mastering Observables and Subjects in Rxjs:]]></title>
            <link>https://medium.com/@javvadirupasri8/mastering-observables-and-subjects-in-rxjs-4f03d5c08de3?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/4f03d5c08de3</guid>
            <category><![CDATA[observables]]></category>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[rxjs]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Thu, 27 Apr 2023 08:14:47 GMT</pubDate>
            <atom:updated>2023-04-27T08:58:17.535Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sZl6M4tZR7aApg-3H5m6UA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pK_xNWp-HPrs5bLaIyouuA.png" /></figure><p>Let’s start from the basics and gradually progress towards more advanced concepts in RxJS in Angular</p><h4>Observables and Observers:</h4><p>Observables are the foundation of RxJS, representing a <strong><em>stream of data that can be observed over time</em>.</strong> Observers are the <strong><em>consumers of these streams</em>,</strong> listening for emitted data and reacting accordingly.</p><p>Observables and Observers are similar to the concepts of events and event handlers in C#.</p><h4>Observables:</h4><p>In Angular, you can create an Observable using the Observable class from the rxjs library. An Observable can emit data asynchronously over time, and can be subscribed by Observers to receive the emitted data.</p><p>Example in Angular:</p><pre>import { Observable } from &#39;rxjs&#39;;<br><br>// Create an Observable that emits a stream of numbers<br>const numbers$ = new Observable(observer =&gt; {<br>  let count = 1;<br>  const intervalId = setInterval(() =&gt; {<br>    observer.next(count++);<br>  }, 1000);<br><br>  // Cleanup logic when the Observable is unsubscribed<br>  return () =&gt; {<br>    clearInterval(intervalId);<br>  };<br>});<br><br>// Subscribe to the Observable to receive the emitted numbers<br>numbers$.subscribe(value =&gt; console.log(value));</pre><h4>Observers:</h4><p>In Angular, an Observer is an object that defines how to handle the emitted data from an Observable.</p><p><strong>It has three optional methods</strong>:</p><p>next for handling the emitted data</p><p>error for handling any errors</p><p>complete for handling the completion of the Observable.</p><p>Example in Angular:</p><pre>import { Observable } from &#39;rxjs&#39;;<br><br>// Create an Observable that emits a stream of numbers<br>const numbers$ = new Observable(observer =&gt; {<br>  let count = 1;<br>  const intervalId = setInterval(() =&gt; {<br>    observer.next(count++);<br>  }, 1000);<br><br>  // Cleanup logic when the Observable is unsubscribed<br>  return () =&gt; {<br>    clearInterval(intervalId);<br>  };<br>});<br><br>// Define an Observer to handle the emitted numbers<br>const observer = {<br>  next: value =&gt; console.log(value),<br>  error: err =&gt; console.error(err),<br>  complete: () =&gt; console.log(&#39;Observable completed&#39;)<br>};<br><br>// Subscribe the Observer to the Observable<br>numbers$.subscribe(observer);</pre><ol><li>Operators: Operators are functions that allow you to transform, filter, and combine data streams emitted by Observables.They are similar to LINQ operators in C#.</li></ol><ul><li>Transformation Operators: Transformation operators allow you to transform the data emitted by an Observable into a different format or structure.</li><li>Example in Angular with map operator:</li></ul><pre>import { of } from &#39;rxjs&#39;;<br>import { map } from &#39;rxjs/operators&#39;;<br><br>// Create an observable that emits a stream of numbers<br>const numbers$ = of(1, 2, 3, 4, 5);<br><br>// Use map operator to square each number in the stream<br>const squaredNumbers$ = numbers$.pipe(<br>  map(num =&gt; num * num)<br>);<br><br>// Subscribe to the transformed data stream<br>squaredNumbers$.subscribe(value =&gt; console.log(value));</pre><ul><li>Filtering Operators: Filtering operators allow you to filter the data emitted by an Observable based on a given condition.</li></ul><p>Example in Angular with filter operator:</p><pre>import { of } from &#39;rxjs&#39;;<br>import { filter } from &#39;rxjs/operators&#39;;<br><br>// Create an observable that emits a stream of numbers<br>const numbers$ = of(1, 2, 3, 4, 5);<br><br>// Use filter operator to get only even numbers from the stream<br>const evenNumbers$ = numbers$.pipe(<br>  filter(num =&gt; num % 2 === 0)<br>);<br><br>// Subscribe to the filtered even numbers stream<br>evenNumbers$.subscribe(value =&gt; console.log(value));</pre><h4>Subjects:</h4><p>Subjects are both Observables and Observers, which allows you to emit and subscribe to data streams directly.</p><p>Subjects are similar to the concept of event emitters in C#.</p><p>Example in Angular with Subject:</p><pre>import { Subject } from &#39;rxjs&#39;;<br><br>// Create a Subject to emit and subscribe to a stream of numbers<br>const numbersSubject$ = new Subject&lt;number&gt;();<br><br>// Subscribe to the Subject to receive emitted numbers<br>numbersSubject$.subscribe(value =&gt; console.log(value));<br><br>// Emit numbers to the Subject<br>numbersSubject$.next(1);<br>numbersSubject$.next(2);<br>numbersSubject$.next(3);</pre><h4><strong>Hot and Cold Observables:</strong></h4><p>Observables can be categorized into two types</p><ol><li>Hot</li><li>Cold.</li></ol><p><strong>Hot Observables</strong> emit data regardless of whether there are any subscribers <strong>Cold Observables</strong> only emit data when there are active subscribers.</p><p>Example in Angular with Hot and Cold Observables:</p><pre>import { interval, fromEvent } from &#39;rxjs&#39;;<br><br>// Hot Observable - emits data regardless of subscribers<br>const hotObservable$ = interval(1000);<br><br>// Cold Observable - emits data only when subscribed<br>const button = document.querySelector(&#39;button&#39;);<br>const coldObservable$ = fromEvent(button, &#39;click&#39;);<br><br>// Subscribe to both Observables<br>hotObservable$.subscribe(value =&gt; console.log(`Hot: ${value}`));<br>coldObservable$.subscribe(value =&gt; console.log(`Cold: ${value}`));</pre><h4>Error handling:</h4><p>RxJS provides operators for handling errors in Observables, such as catchError and retry, which allow you to handle errors and retries in a stream of data.</p><p>Example in Angular with error handling:</p><pre>import { of } from &#39;rxjs&#39;;<br>import { catchError, retry } from &#39;rxjs/operators&#39;;<br><br>// Create an observable that may emit an error<br>const numbers$ = of(1, 2, 3, 4, 5, &#39;six&#39;);<br><br>// Use catchError operator to handle errors<br>const numbersWithErrorHandled$ = numbers$.pipe(<br>  catchError(err =&gt; of(&#39;Error occurred:&#39;, err))<br>);<br><br>// Use retry operator to retry the observable in case of error<br>const numbersWithRetry$ = numbers$.pipe(<br>  retry(2) // Retry 2 times in case of error<br>);<br><br>// Subscribe to the error handled and retried observables<br>numbersWithErrorHandled$.subscribe(value =&gt; console.log(value));<br>numbersWithRetry$.subscribe(value =&gt; console.log(value));</pre><h4>Custom operators:</h4><p>RxJS allows you to create your own custom operators by composing existing operators or extending the Observable class. This gives you flexibility to create reusable and specialized operators for your specific use cases.</p><p>Example in Angular with a custom operator:</p><pre>import { Observable, OperatorFunction } from &#39;rxjs&#39;;<br>import { map } from &#39;rxjs/operators&#39;;<br><br>// Custom operator to multiply each emitted number by a given factor<br>function multiplyBy(factor: number): OperatorFunction&lt;number, number&gt; {<br>  return (source: Observable&lt;number&gt;) =&gt;<br>    source.pipe(map(num =&gt; num * factor));<br>}<br><br>// Create an observable that emits a stream of numbers<br>const numbers$ = of(1, 2, 3, 4, 5);<br><br>// Use the custom multiplyBy operator to multiply each number by 10<br>const multipliedNumbers$ = numbers$.pipe(multiplyBy(10));<br><br>// Subscribe to the multiplied numbers<br>multipliedNumbers$.subscribe(value =&gt; console.log(value));</pre><h4>Schedulers:</h4><p>RxJS allows you to control the execution context or scheduler of an Observable. Schedulers provide options for managing concurrency, controlling timing, and executing code on specific threads or contexts.</p><p>Example in Angular with schedulers:</p><pre>import { of, asyncScheduler } from &#39;rxjs&#39;;<br>import { observeOn } from &#39;rxjs/operators&#39;;<br><br>// Create an observable that emits a stream of numbers<br>const numbers$ = of(1, 2, 3, 4, 5);<br><br>// Use observeOn operator to specify an asyncScheduler for subscription<br>const asyncNumbers$ = numbers$.pipe(observeOn(asyncScheduler));<br><br>// Subscribe to the numbers with asyncScheduler<br>asyncNumbers$.subscribe(value =&gt; console.log(value));<br><br>// Use observeOn operator with other schedulers like asapScheduler or queueScheduler<br>const asapNumbers$ = numbers$.pipe(observeOn(asapScheduler));<br>const queueNumbers$ = numbers$.pipe(observeOn(queueScheduler));</pre><h4>Multicasting:</h4><p>By default, Observables are unicast, meaning each subscription creates a separate execution of the Observable.</p><p>However, you can multicast Observables to share a single execution among multiple subscribers, which can improve performance and reduce duplicated work.</p><p>Example in Angular with multicasting:</p><pre>import { interval, Subject } from &#39;rxjs&#39;;<br>import { multicast, refCount } from &#39;rxjs/operators&#39;;<br><br>// Create a hot Observable that emits numbers every second<br>const numbers$ = interval(1000).pipe(multicast(() =&gt; new Subject()), refCount());<br><br>// Subscribe to the hot Observable from multiple subscribers<br>numbers$.subscribe(value =&gt; console.log(`Subscriber 1: ${value}`));<br>numbers$.subscribe(value =&gt; console.log(`Subscriber 2: ${value}`));<br><br>// Start the execution of the hot Observable<br>numbers$.connect();</pre><h4>Customizing the Observable:</h4><p>You can also customize the behavior of an Observable by extending the Observable class and implementing your own logic for emitting values, handling errors, and managing subscriptions.</p><p>Example in Angular with a custom Observable:</p><pre>import { Observable } from &#39;rxjs&#39;;<br><br>// Custom Observable that emits a sequence of numbers<br>class MyNumbersObservable extends Observable&lt;number&gt; {<br>  private currentNumber = 1;<br><br>  constructor(private maxNumber: number) {<br>    super(subscriber =&gt; {<br>      const intervalId = setInterval(() =&gt; {<br>        if (this.currentNumber &lt;= maxNumber) {<br>          subscriber.next(this.currentNumber++);<br>        } else {<br>          subscriber.complete();<br>          clearInterval(intervalId);<br>        }<br>      }, 1000);<br>    });<br>  }<br>}<br><br>// Create an instance of the custom Observable<br>const myNumbers$ = new MyNumbersObservable(5);<br><br>// Subscribe to the custom Observable<br>myNumbers$.subscribe(value =&gt; console.log(value));</pre><h4>Backpressure:</h4><p>RxJS provides mechanisms for handling backpressure, which occurs when the rate of emission from an Observable is higher than the rate of consumption by subscribers. Backpressure strategies allow you to control how data is buffered, dropped, or managed when dealing with high-rate data streams.</p><p>Example in Angular with backpressure:</p><pre>import { interval, bufferTime } from &#39;rxjs&#39;;<br><br>// Create a fast-emitting Observable that emits numbers every 100ms<br>const fastNumbers$ = interval(100);<br><br>// Use bufferTime operator to buffer emitted numbers for every 1 second<br>const bufferedNumbers$ = fastNumbers$.pipe(bufferTime(1000));<br><br>// Subscribe to the buffered numbers<br>bufferedNumbers$.subscribe(values =&gt; console.log(values));</pre><h4>Error Handling:</h4><p>RxJS provides operators for handling errors that may occur in the Observable stream.</p><p>You can catch and handle errors, retry failed Observables, and take other actions to gracefully handle errors in your application.</p><p>Example in Angular with error handling:</p><pre>import { of } from &#39;rxjs&#39;;<br>import { catchError, retry } from &#39;rxjs/operators&#39;;<br><br>// Create an Observable that may throw an error<br>const numbers$ = of(1, 2, 3, 4, 5, &#39;invalid&#39;, 7, 8, 9);<br><br>// Use catchError operator to catch and handle errors<br>const safeNumbers$ = numbers$.pipe(<br>  catchError(error =&gt; {<br>    console.error(`Error: ${error}`);<br>    return of(&#39;Error occurred. Continuing with default value.&#39;);<br>  })<br>);<br><br>// Use retry operator to retry failed Observables<br>const retryNumbers$ = safeNumbers$.pipe(<br>  retry(2) // Retry failed Observables up to 2 times<br>);<br><br>// Subscribe to the safe and retrying numbers<br>retryNumbers$.subscribe(value =&gt; console.log(value));</pre><h4>Custom Operators:</h4><p>RxJS allows you to create custom operators by combining existing operators or by implementing your own logic for transforming or filtering values in the Observable stream. Custom operators can provide reusable and specialized functionality for your specific use cases.</p><p>Example in Angular with a custom operator:</p><pre>import { Observable, OperatorFunction } from &#39;rxjs&#39;;<br>import { filter } from &#39;rxjs/operators&#39;;<br><br>// Custom operator that filters out odd numbers<br>function filterOutOddNumbers(): OperatorFunction&lt;number, number&gt; {<br>  return (source: Observable&lt;number&gt;) =&gt;<br>    new Observable&lt;number&gt;(subscriber =&gt; {<br>      return source.subscribe(value =&gt; {<br>        if (value % 2 === 0) {<br>          subscriber.next(value);<br>        }<br>      });<br>    });<br>}<br><br>// Create an Observable that emits a sequence of numbers<br>const numbers$ = of(1, 2, 3, 4, 5);<br><br>// Use the custom filterOutOddNumbers operator<br>const filteredNumbers$ = numbers$.pipe(filterOutOddNumbers());<br><br>// Subscribe to the filtered numbers<br>filteredNumbers$.subscribe(value =&gt; console.log(value));</pre><p>This is just a brief overview of some of the basic to advanced concepts and features of RxJS. RxJS is a powerful and flexible library that can greatly simplify and enhance your asynchronous programming in Angular or any other JavaScript environment. I recommend referring to the official RxJS documentation for more in-depth explanations and examples.</p><p>I hope this detailed blog post on Observables and subject in Rxjs with examples. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding.</p><p>Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4f03d5c08de3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Pass by Value and Pass by Reference in C# with Real-time Examples]]></title>
            <link>https://towardsdev.com/understanding-pass-by-value-and-pass-by-reference-in-c-with-real-time-examples-e04bd7efbc98?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/e04bd7efbc98</guid>
            <category><![CDATA[pass-by-reference]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[pass-by-value]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Wed, 26 Apr 2023 06:03:47 GMT</pubDate>
            <atom:updated>2023-05-02T09:53:49.746Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Pass by value and pass by reference are two different ways of passing arguments to a method in C#.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/514/1*ayEJRg0yQ0ZIAKiVbpHU7Q.png" /></figure><p>In this blog, we will explore the concepts of pass by value and pass by reference with detailed examples along with real-time examples to illustrate their differences.</p><h4>Pass by Value:</h4><p>In C#, when we pass an argument to a method by value, a copy of the value of the argument is passed to the method. This means that any changes made to the parameter inside the method do not affect the original argument outside the method.</p><p>Let’s take an example to understand pass by value:</p><pre>public class MathUtility<br>{<br>    public static void Square(int num)<br>    {<br>        num = num * num; // Changes made to the parameter do not affect the original argument<br>        Console.WriteLine(&quot;Inside the method: &quot; + num);<br>    }<br>}<br><br>public class Program<br>{<br>    static void Main()<br>    {<br>        int number = 5;<br>        Console.WriteLine(&quot;Before calling the method: &quot; + number);<br>        MathUtility.Square(number); // Argument passed by value<br>        Console.WriteLine(&quot;After calling the method: &quot; + number); // Original argument remains unchanged<br>    }<br>}</pre><p><strong>Output:</strong></p><pre>Before calling the method: 5<br>Inside the method: 25<br>After calling the method: 5</pre><p>In this example, we have a static method “Square” in the “MathUtility” class that takes an integer argument “num” by value. Inside the method, we square the value of “num”, but it does not affect the original argument “number” outside the method. When we run the program, we can see that the original argument “number” remains unchanged even after calling the method.</p><h4>Pass by Reference:</h4><p>In C#, when we pass an argument to a method by reference, a reference to the memory location of the argument is passed to the method. This means that any changes made to the parameter inside the method will affect the original argument outside the method.</p><p>Let’s take an example to understand pass by reference:</p><pre>public class MathUtility<br>{<br>    public static void Square(ref int num)<br>    {<br>        num = num * num; // Changes made to the parameter affect the original argument<br>        Console.WriteLine(&quot;Inside the method: &quot; + num);<br>    }<br>}<br><br>public class Program<br>{<br>    static void Main()<br>    {<br>        int number = 5;<br>        Console.WriteLine(&quot;Before calling the method: &quot; + number);<br>        MathUtility.Square(ref number); // Argument passed by reference<br>        Console.WriteLine(&quot;After calling the method: &quot; + number); // Original argument is changed<br>    }<br>}</pre><p><strong>Output</strong>:</p><pre>Before calling the method: 5<br>Inside the method: 25<br>After calling the method: 25</pre><p>In this example, we have a static method “Square” in the “MathUtility” class that takes an integer argument “num” by reference using the ref keyword. Inside the method, we square the value of &quot;num&quot;, and it affects the original argument &quot;number&quot; outside the method. When we run the program, we can see that the original argument &quot;number&quot; is changed after calling the method.</p><p>I hope this detailed blog post on Pass by value and Pass by Reference in C# with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding.</p><p>Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e04bd7efbc98" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/understanding-pass-by-value-and-pass-by-reference-in-c-with-real-time-examples-e04bd7efbc98">Understanding Pass by Value and Pass by Reference in C# with Real-time Examples</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Harnessing the Power of Events and Delegates in C#:]]></title>
            <link>https://towardsdev.com/harnessing-the-power-of-events-and-delegates-in-c-e84332187545?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/e84332187545</guid>
            <category><![CDATA[csharp]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[delegation]]></category>
            <category><![CDATA[backend]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Tue, 25 Apr 2023 13:38:16 GMT</pubDate>
            <atom:updated>2023-04-25T19:50:12.116Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1019/1*ycXXRNYuWNgO3MGWhiYa-w.jpeg" /></figure><h3>A Comprehensive Guide with Real-World Examples</h3><p>Introduction:In today’s software development landscape, event-driven programming has become a crucial paradigm for handling asynchronous tasks efficiently. C# provides powerful features called events and delegates that enable developers to implement event-driven programming effectively. In this comprehensive blog post, we will delve into the world of events and delegates in C#, understand their core concepts, explore various usage scenarios, advantages, disadvantages, and real-world examples to illustrate their practical applications.</p><p><strong>Table of Contents:</strong></p><ol><li>Introduction</li><li>What are Delegates in C#?</li></ol><ul><li>Delegate Basics</li><li>Usage Scenarios</li><li>Advantages and Disadvantages</li><li>Real-World Example</li></ul><p>3. What are Events in C#?</p><ul><li>Event Basics</li><li>Usage Scenarios</li><li>Advantages and Disadvantages</li><li>Real-World Example</li></ul><p>4. Combining Delegates and Events</p><ul><li>Delegate Chaining</li><li>Handling Multiple Events</li></ul><p>5. Advanced Topics</p><ul><li>Anonymous Methods</li><li>Lambda Expressions</li><li>Generic Delegates</li><li>Custom Delegates</li></ul><p>6. Best Practices and Tips</p><ul><li>Proper Use of Events and Delegates</li><li>Memory Management</li><li>Exception Handling</li><li>Debugging Tips</li></ul><p>7. Conclusion</p><h4>What are Delegates in C#?</h4><p><strong>Delegate Basics</strong>: Delegates in C# are type-safe function pointers that refer to methods with specific signatures. They allow methods to be assigned to delegate objects and called at runtime. A delegate is declared using the delegate keyword, followed by the return type, delegate name, and the parameter list in parentheses. Delegates can have different types, depending on the method signatures they can point to.</p><p><strong>Usage Scenarios:</strong> Delegates are widely used in scenarios such as event handling, callback functions, and asynchronous programming. For example, consider a scenario where a math calculator needs to perform arithmetic operations:</p><pre>public delegate double CalculatorDelegate(double a, double b);</pre><pre>public class Calculator<br>{<br>    public static double Add(double a, double b)<br>    {<br>        return a + b;<br>    }</pre><pre>    public static double Subtract(double a, double b)<br>    {<br>        return a - b;<br>    }</pre><pre>    public static double Multiply(double a, double b)<br>    {<br>        return a * b;<br>    }</pre><pre>    public static double Divide(double a, double b)<br>    {<br>        return a / b;<br>    }<br>}</pre><p>In this example, we define a CalculatorDelegate delegate that references methods for arithmetic operations. We can use this delegate to perform arithmetic operations dynamically at runtime by assigning different methods to it.</p><h4>Advantages and Disadvantages of Delegates:</h4><p>Delegates offer several advantages, including:</p><ol><li><strong>Flexibility</strong>: Delegates allow methods to be assigned to delegate objects and called at runtime, making them highly flexible and dynamic.</li><li><strong>Code Reusability</strong>: Delegates promote code reusability by allowing multiple methods with the same signature to be assigned to the same delegate, enabling different implementations for the same functionality.</li><li><strong>Separation of Concerns</strong>: Delegates facilitate the separation of concerns by allowing the decoupling of event publishers and subscribers, ensuring loose coupling between components.</li></ol><p>However, delegates also have some disadvantages, including:</p><ol><li><strong>Complexity</strong>: Delegates can introduce complexity to code due to their dynamic nature and potential for multiple methods to be assigned to the same delegate.</li><li><strong>Performance Overhead</strong>: Delegates may introduce a performance overhead due to the dynamic invocation of methods at runtime.</li><li><strong>Memory Management</strong>: Delegates can cause memory leaks if not properly handled, as they hold references to the methods they point to.</li></ol><h4>Real-World Example:</h4><p>Let’s consider a real-world example of a stock market application that uses delegates for event handling. In this scenario, the application has a Stock class that represents a stock with properties such as Symbol, Price, and ChangePercentage. The application also has a StockMarket class that is responsible for updating the stock prices and notifying the subscribers when the stock prices change.</p><pre>public class Stock<br>{<br>    public string Symbol { get; set; }<br>    public decimal Price { get; set; }<br>    public decimal ChangePercentage { get; set; }<br>}</pre><pre>public class StockMarket<br>{<br>    private List&lt;Stock&gt; stocks = new List&lt;Stock&gt;();<br>    public delegate void StockPriceChangedEventHandler(object sender, Stock stock);<br>    public event StockPriceChangedEventHandler StockPriceChanged;</pre><pre>    public void AddStock(string symbol, decimal price)<br>    {<br>        var stock = new Stock { Symbol = symbol, Price = price, ChangePercentage = 0 };<br>        stocks.Add(stock);<br>    }</pre><pre>    public void UpdateStockPrice(string symbol, decimal newPrice)<br>    {<br>        var stock = stocks.FirstOrDefault(s =&gt; s.Symbol == symbol);<br>        if (stock != null)<br>        {<br>            var oldPrice = stock.Price;<br>            stock.Price = newPrice;<br>            stock.ChangePercentage = ((newPrice - oldPrice) / oldPrice) * 100;</pre><pre>            // Raise the event to notify subscribers<br>            OnStockPriceChanged(this, stock);<br>        }<br>    }</pre><pre>    protected virtual void OnStockPriceChanged(object sender, Stock stock)<br>    {<br>        // Check if there are any subscribers to the event<br>        StockPriceChanged?.Invoke(sender, stock);<br>    }<br>}</pre><p>In this example, the StockMarket class uses a delegate StockPriceChangedEventHandler and an event StockPriceChanged to handle stock price changes. The StockPriceChanged event is raised whenever the UpdateStockPrice method is called, notifying the subscribers with the updated stock object.</p><p><strong>Usage of Delegates in the Example</strong>:</p><ul><li>The StockPriceChangedEventHandler delegate is used to define the signature of the event handler method that will be called when the StockPriceChanged event is raised.</li><li>The event keyword is used to define the StockPriceChanged event, which is a mechanism for subscribers to register their event handler methods to be called when the event is raised.</li><li>The OnStockPriceChanged method is used to raise the StockPriceChanged event and invoke the registered event handler methods.</li></ul><p><strong>Advantages of Delegates in the Example</strong>:</p><ul><li>Flexibility: Delegates allow dynamic event handling, where subscribers can register their event handler methods at runtime, providing flexibility in managing event subscriptions.</li><li>Code Reusability: Delegates enable multiple subscribers to register their event handler methods to the same event, allowing for code reusability and extensibility.</li><li>Separation of Concerns: Delegates help to decouple the event publisher (StockMarket class) from the event subscribers (subscribers&#39; event handler methods), promoting separation of concerns and maintainability of the code.</li></ul><p><strong>Disadvantages of Delegates in the Example</strong>:</p><ul><li>Complexity: Delegates introduce complexity in managing event subscriptions and handling event invocation, which may require additional effort for debugging and maintenance.</li><li>Performance Overhead: Delegates may introduce a performance overhead due to the dynamic invocation of event handler methods at runtime, especially when multiple event handlers are involved.</li><li>Memory Management: Delegates may hold references to event subscribers, which can cause memory leaks if not properly managed, as the subscribers may not be garbage collected.</li></ul><h4>What are Events in C#?</h4><p>Event Basics: Events in C# are a special type of delegate that provides a standardized way of declaring, raising, and handling events. Events are based on delegates and provide a more controlled way of handling event subscriptions and invocations. Events are used to notify objects (event subscribers) when an action or an occurrence (event) happens in another object (event publisher).</p><p><strong>Events have the following key characteristics</strong>:</p><ol><li>Event Publisher: The object that raises an event is called the event publisher. In the previous example, the StockMarket class is the event publisher as it raises the StockPriceChanged event.</li><li>Event Subscriber: The object that handles an event is called the event subscriber. In the previous example, any object that subscribes to the StockPriceChanged event by registering its event handler method is an event subscriber.</li><li>Event Handler: The method that is registered to handle an event is called the event handler. In the previous example, the StockPriceChangedEventHandler delegate is used to define the signature of the event handler method that will be called when the StockPriceChanged event is raised.</li><li>Event Declaration: Events are declared using the event keyword followed by the delegate type that defines the event handler method signature. In the previous example, the StockPriceChanged event is declared using the StockPriceChangedEventHandler delegate.</li><li>Event Subscription: Objects can subscribe to events by registering their event handler methods to the event using the += operator. In the previous example, the event handler methods are registered to the StockPriceChanged event using the += operator.</li><li>Event Invocation: Events are raised using the Invoke method of the event delegate or by simply calling the event like a method. In the previous example, the StockPriceChanged event is raised by invoking the StockPriceChanged delegate using the OnStockPriceChanged method.</li><li>Event Unsubscription: Objects can unsubscribe from events by unregistering their event handler methods from the event using the -= operator. In the previous example, the event handler methods can be unregistered from the StockPriceChanged event using the -= operator.</li></ol><p>Now let’s take a look at an example scenario where events and delegates can be used in a real-time application.</p><p>Imagine you are building a chat application that allows users to send messages to each other in real-time. You have a ChatServer class that is responsible for handling incoming messages and notifying the subscribers when new messages arrive. The ChatServer class has a MessageReceived event that is raised whenever a new message is received. Users can subscribe to this event to be notified when a new message arrives.</p><pre>public class ChatServer<br>{<br>    public delegate void MessageReceivedEventHandler(object sender, MessageEventArgs e);<br>    public event MessageReceivedEventHandler MessageReceived;</pre><pre>    public void ReceiveMessage(string sender, string message)<br>    {<br>        // Process the incoming message and raise the event<br>        var messageEventArgs = new MessageEventArgs(sender, message);<br>        OnMessageReceived(this, messageEventArgs);<br>    }</pre><pre>    protected virtual void OnMessageReceived(object sender, MessageEventArgs e)<br>    {<br>        // Check if there are any subscribers to the event<br>        MessageReceived?.Invoke(sender, e);<br>    }<br>}</pre><pre>public class MessageEventArgs : EventArgs<br>{<br>    public string Sender { get; }<br>    public string Message { get; }</pre><pre>    public MessageEventArgs(string sender, string message)<br>    {<br>        Sender = sender;<br>        Message = message;<br>    }<br>}</pre><p>In this example, the ChatServer class uses a delegate MessageReceivedEventHandler and an event MessageReceived to handle incoming messages. The MessageReceived event is raised whenever a new message is received, notifying the subscribers with the sender and message information.</p><p><strong>Usage of Delegates in the Example:</strong></p><ul><li>The MessageReceivedEventHandlerdelegate is used to define the signature of the event handler method that will be called when theMessageReceived` event is raised.</li></ul><p><strong>Usage of Events in the Example</strong>:</p><ul><li>The MessageReceived event is declared using the MessageReceivedEventHandler delegate, which defines the signature of the event handler method for handling incoming messages.</li><li>Subscribers can register their event handler methods to the MessageReceived event using the += operator, and unregister them using the -= operator.</li><li>The MessageReceived event is raised by invoking the MessageReceived delegate using the OnMessageReceived method, which notifies all subscribers with the sender and message information.</li></ul><p>Now, let’s see how this chat application scenario demonstrates the advantages of using events and delegates in C#.</p><p><strong>Advantages of Events and Delegates:</strong></p><ol><li>Loose Coupling: Events and delegates allow for loose coupling between objects in a C# application. In the chat application example, the ChatServer class does not need to know about the subscribers or how they handle incoming messages. It simply raises the MessageReceived event, and any registered subscribers&#39; event handler methods will be called. This allows for flexibility and easy maintenance, as changes in the event publisher do not directly affect the event subscribers.</li><li>Extensibility: Events and delegates provide a way to extend the functionality of an application without modifying existing code. In the chat application example, new subscribers can easily register their event handler methods to the MessageReceived event without modifying the ChatServer class. Similarly, event subscribers can be removed without affecting the event publisher. This promotes code reusability and scalability.</li><li>Multiple Subscribers: Events and delegates allow for multiple subscribers to handle an event. In the chat application example, multiple users can subscribe to the MessageReceived event and receive notifications when new messages arrive. This enables a one-to-many communication pattern, where a single event can be handled by multiple objects.</li><li>Clear Separation of Concerns: Events and delegates help in separating the concerns of different parts of an application. In the chat application example, the ChatServer class is responsible for handling incoming messages, and the event subscribers are responsible for handling the received messages according to their specific logic. This promotes better code organization and maintainability.</li><li>Encapsulation: Events and delegates encapsulate the event handling logic in a separate class or method. In the chat application example, the event handling logic is encapsulated in the event handler methods of the subscribers, which allows for better encapsulation and abstraction of the event handling logic.</li></ol><p><strong>Disadvantages of Events and Delegates:</strong></p><ol><li>Complexity: Events and delegates can introduce complexity in the code, especially when dealing with multiple events and subscribers. Care must be taken to properly manage event subscriptions, unsubscriptions, and event invocations to avoid potential issues like memory leaks or event handling order.</li><li>Overhead: Events and delegates can introduce overhead in terms of performance and memory usage. Invoking events and handling them requires additional processing compared to direct method calls. However, the overhead is usually negligible in most scenarios and the benefits of using events and delegates usually outweigh the costs.</li></ol><p>In conclusion, events and delegates are powerful tools in C# that provide a robust and flexible way to handle events and notifications in an object-oriented application. They promote loose coupling, extensibility, and encapsulation, making the code more maintainable and scalable. However, they should be used judiciously, considering the potential complexity and overhead they may introduce. By understanding the concepts of events and delegates and their usage in real-time scenarios like the chat application example, developers can leverage them effectively in their C# applications to achieve efficient event-driven programming.</p><h4>Combining Delegates and Events:</h4><p>Delegates in C# can be combined to form multicast delegates, which can be used to invoke multiple methods sequentially or concurrently. This allows for powerful event handling scenarios where multiple subscribers can handle an event in a specific order or simultaneously.</p><p><strong>Example</strong>: Let’s consider an online auction system where multiple bidders can bid on an item. We can use a multicast delegate to handle the bidding process. The auctioneer can define a delegate that represents the bidding action, and bidders can register their methods as event handlers to this delegate. When the auctioneer raises the bidding event, all registered methods will be invoked in the order they were registered, allowing multiple bidders to bid on the item simultaneously.</p><pre>using System;</pre><pre>public delegate void BiddingHandler(string bidderName, decimal bidAmount);</pre><pre>public class Auctioneer<br>{<br>    public event BiddingHandler BiddingEvent;</pre><pre>    public void RaiseBiddingEvent(string bidderName, decimal bidAmount)<br>    {<br>        if (BiddingEvent != null)<br>        {<br>            BiddingEvent(bidderName, bidAmount);<br>        }<br>    }<br>}</pre><pre>public class Bidder<br>{<br>    public string Name { get; }</pre><pre>    public Bidder(string name)<br>    {<br>        Name = name;<br>    }</pre><pre>    public void PlaceBid(string itemName, decimal bidAmount)<br>    {<br>        Console.WriteLine($&quot;{Name} placed a bid of {bidAmount} on {itemName}&quot;);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Auctioneer auctioneer = new Auctioneer();<br>        Bidder bidder1 = new Bidder(&quot;Bidder1&quot;);<br>        Bidder bidder2 = new Bidder(&quot;Bidder2&quot;);</pre><pre>        // Register event handlers<br>        auctioneer.BiddingEvent += bidder1.PlaceBid;<br>        auctioneer.BiddingEvent += bidder2.PlaceBid;</pre><pre>        // Raise the event<br>        auctioneer.RaiseBiddingEvent(&quot;Item1&quot;, 100);<br>    }<br>}</pre><h4>Handling Multiple Events:</h4><p>In some scenarios, an object may need to handle multiple events from different sources. C# provides a simple way to handle multiple events using the “+=” operator to attach event handlers for different events to the same delegate.</p><p>Example: In a multimedia player application, an object may need to handle events from different media sources, such as video playback, audio playback, and subtitle display. The object can define a delegate that represents the actions for these events, and multiple media sources can register their event handlers to this delegate using the “+=” operator. When any of the media sources raise an event, the registered event handlers will be invoked accordingly.</p><pre>using System;</pre><pre>public class MediaPlayer<br>{<br>    public event EventHandler VideoPlaybackEvent;<br>    public event EventHandler AudioPlaybackEvent;<br>    public event EventHandler SubtitleDisplayEvent;</pre><pre>    public void PlayVideo(string videoName)<br>    {<br>        Console.WriteLine($&quot;Playing video: {videoName}&quot;);<br>        VideoPlaybackEvent?.Invoke(this, EventArgs.Empty);<br>    }</pre><pre>    public void PlayAudio(string audioName)<br>    {<br>        Console.WriteLine($&quot;Playing audio: {audioName}&quot;);<br>        AudioPlaybackEvent?.Invoke(this, EventArgs.Empty);<br>    }</pre><pre>    public void DisplaySubtitle(string subtitle)<br>    {<br>        Console.WriteLine($&quot;Displaying subtitle: {subtitle}&quot;);<br>        SubtitleDisplayEvent?.Invoke(this, EventArgs.Empty);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        MediaPlayer mediaPlayer = new MediaPlayer();</pre><pre>        // Register event handlers for different events<br>        mediaPlayer.VideoPlaybackEvent += (sender, e) =&gt; Console.WriteLine(&quot;Video playback event&quot;);<br>        mediaPlayer.AudioPlaybackEvent += (sender, e) =&gt; Console.WriteLine(&quot;Audio playback event&quot;);<br>        mediaPlayer.SubtitleDisplayEvent += (sender, e) =&gt; Console.WriteLine(&quot;Subtitle display event&quot;);</pre><pre>        // Raise different events<br>        mediaPlayer.PlayVideo(&quot;Video1&quot;);<br>        mediaPlayer.PlayAudio(&quot;Audio1&quot;);<br>        mediaPlayer.DisplaySubtitle(&quot;Subtitle1&quot;);<br>    }<br>}</pre><h4>Advanced Topics:</h4><p><strong>Anonymous Methods</strong>: C# allows defining anonymous methods, which are nameless methods that can be used as event handlers. Anonymous methods provide a concise way to define small, inline event handler methods without explicitly declaring a separate method. Anonymous methods can be useful in scenarios where the event handler logic is short and simple.</p><p><strong>Example</strong>: In a button click event handler, instead of declaring a separate method for the event handler, an anonymous method can be defined directly inside the event handler registration code. This can make the code more concise and easier to read, especially for short event handler logic.</p><pre>using System;</pre><pre>public class Button<br>{<br>    public event EventHandler Click;</pre><pre>    public void OnClick()<br>    {<br>        Click?.Invoke(this, EventArgs.Empty);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button button = new Button();</pre><pre>        // Register event handler using anonymous method<br>        button.Click += (sender, e) =&gt;<br>        {<br>            Console.WriteLine(&quot;Button clicked&quot;);<br>        };</pre><pre>        // Raise the event<br>        button.OnClick();<br>    }<br>}</pre><p><strong>Lambda</strong> <strong>Expressions</strong>: Lambda expressions are another way to define inline event handler methods in C#. Lambda expressions are concise and provide a convenient way to define event handlers using a functional programming approach. Lambda expressions can be used with delegates and events to provide compact and expressive event handling code.</p><p><strong>Example</strong>: Instead of defining an anonymous method as an event handler, a lambda expression can be used to define the event handler directly in the event registration code. This can make the code more concise and expressive, especially for small event handling logic.</p><pre>using System;</pre><pre>public class Button<br>{<br>    public event EventHandler Click;</pre><pre>    public void OnClick()<br>    {<br>        Click?.Invoke(this, EventArgs.Empty);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button button = new Button();</pre><pre>        // Register event handler using lambda expression<br>        button.Click += (sender, e) =&gt; Console.WriteLine(&quot;Button clicked&quot;);</pre><pre>        // Raise the event<br>        button.OnClick();<br>    }<br>}</pre><p><strong>Generic Delegates</strong>: C# provides generic delegates that can be used with different types of event handlers. Generic delegates allow for more flexibility and type safety in event handling scenarios where the event handlers may have different parameter types or return types.</p><p><strong>Example</strong>: Instead of using a specific delegate type for a specific event, a generic delegate can be used to handle events with different parameter types, such as EventHandler&lt;TEventArgs&gt;. This allows for more reusable event handling code that can handle events with different event arguments.</p><pre>using System;</pre><pre>public delegate void Action&lt;T&gt;(T arg);</pre><pre>public class Button&lt;T&gt;<br>{<br>    public event Action&lt;T&gt; Click;</pre><pre>    public void OnClick(T data)<br>    {<br>        Click?.Invoke(data);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button&lt;int&gt; button1 = new Button&lt;int&gt;();<br>        Button&lt;string&gt; button2 = new Button&lt;string&gt;();</pre><pre>        // Register event handler for int type<br>        button1.Click += (data) =&gt; Console.WriteLine($&quot;Button clicked with data: {data}&quot;);</pre><pre>        // Register event handler for string type<br>        button2.Click += (data) =&gt; Console.WriteLine($&quot;Button clicked with data: {data}&quot;);</pre><pre>        // Raise events with different data types<br>        button1.OnClick(10);<br>        button2.OnClick(&quot;Hello&quot;);<br>    }<br>}</pre><p><strong>Custom Delegates</strong>: In addition to the built-in delegates in C#, developers can define their own custom delegates to represent event handlers with specific signatures. Custom delegates can provide more descriptive and type-safe event handling code, especially in complex scenarios where the event handlers have specific requirements.</p><p><strong>Example</strong>: In a custom logging framework, a custom delegate with a specific signature can be defined to represent the logging action, such as LogEventHandler. Event handlers can then be registered using this custom delegate, providing a more descriptive and type-safe way to handle logging events.</p><pre>using System;</pre><pre>public delegate void CalculationHandler(int num1, int num2);</pre><pre>public class Calculator<br>{<br>    public event CalculationHandler CalculationEvent;</pre><pre>    public void Add(int num1, int num2)<br>    {<br>        int result = num1 + num2;<br>        CalculationEvent?.Invoke(num1, num2);<br>        Console.WriteLine($&quot;Addition result: {result}&quot;);<br>    }</pre><pre>    public void Subtract(int num1, int num2)<br>    {<br>        int result = num1 - num2;<br>        CalculationEvent?.Invoke(num1, num2);<br>        Console.WriteLine($&quot;Subtraction result: {result}&quot;);<br>    }<br>}</pre><pre>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Calculator calculator = new Calculator();</pre><pre>        // Register event handler<br>        calculator.CalculationEvent += (num1, num2) =&gt; Console.WriteLine($&quot;Calculation performed with {num1} and {num2}&quot;);</pre><pre>        // Perform calculations<br>        calculator.Add(5, 3);<br>        calculator.Subtract(10, 7);<br>    }<br>}</pre><h4>Best Practices and Tips:</h4><p><strong>Proper Use of Events and Delegates</strong>: It’s important to use events and delegates appropriately in the right scenarios. Events should be used for notifications or notifications of changes, while delegates can be used for callbacks or function pointers.</p><ul><li>Define delegates with appropriate signature matching the methods that will be subscribed to them.</li><li>Use the event keyword to declare events, which ensures that the event can only be subscribed to and unsubscribed from within the declaring class.</li><li>Use protected virtual methods to raise events, allowing derived classes to override and extend the behavior of event invocation.</li><li>Always check for null before invoking an event to avoid null reference exceptions.</li></ul><pre>public class MyClass<br>{<br>    // Declare an event using the event keyword<br>    public event EventHandler MyEvent;</pre><pre>    // Method to raise the event<br>    protected virtual void OnMyEvent(EventArgs e)<br>    {<br>        MyEvent?.Invoke(this, e);<br>    }<br>}</pre><p><strong>Memory Management:</strong></p><ul><li>Be cautious with long-lived events that can cause memory leaks. Always unsubscribe from events when they are no longer needed, especially in cases where the subscriber has a longer lifespan than the publisher.</li><li>Use weak event pattern or weak references to prevent event handlers from preventing garbage collection of objects.</li></ul><pre>public class Button<br>{<br>    // Declare a weak event using WeakEventManager<br>    private WeakEventManager&lt;Button, EventArgs&gt; _clickEventManager = new WeakEventManager&lt;Button, EventArgs&gt;();</pre><pre>    // Declare an event for button click<br>    public event EventHandler Click<br>    {<br>        add =&gt; _clickEventManager.AddEventHandler(this, value);<br>        remove =&gt; _clickEventManager.RemoveEventHandler(this, value);<br>    }</pre><pre>    // Method to raise the Click event<br>    public void OnClick()<br>    {<br>        _clickEventManager.HandleEvent(this, EventArgs.Empty, nameof(Click));<br>    }<br>}</pre><p><strong>Exception Handling:</strong></p><ul><li>Handle exceptions appropriately in event handlers to prevent crashing the application.</li><li>Use try-catch blocks within event handlers to catch and handle any exceptions that may occur.</li></ul><pre>private void Button_Click(object sender, EventArgs e)<br>{<br>    try<br>    {<br>        // Code that may throw exceptions<br>    }<br>    catch (Exception ex)<br>    {<br>        // Handle the exception<br>        Console.WriteLine($&quot;An exception occurred: {ex.Message}&quot;);<br>    }<br>}</pre><p><strong>Debugging Tips:</strong></p><ul><li>Use event handlers’ stack trace and call stack information to identify the source of an event.</li><li>Utilize debugger breakpoints and watches to track the flow of events and delegate invocations.</li></ul><pre>private void Button_Click(object sender, EventArgs e)<br>{<br>    // Use debugger breakpoints to track the flow of events<br>    Console.WriteLine(&quot;Button_Click is called&quot;);<br>}</pre><h4>Conclusion:</h4><p>Events and delegates are powerful features in C# that provide a way to implement event-driven programming and enable loose coupling between components. Proper use of events and delegates can lead to cleaner and more maintainable code. By following best practices, handling memory management, exception handling, and utilizing debugging tips, you can ensure effective usage of events and delegates in your C# applications.</p><p>I hope this detailed blog post on events and delegates in C# with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding. Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e84332187545" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/harnessing-the-power-of-events-and-delegates-in-c-e84332187545">Harnessing the Power of Events and Delegates in C#:</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Harnessing the Power of Events and Delegates in C#:]]></title>
            <link>https://medium.com/@javvadirupasri8/harnessing-the-power-of-events-and-delegates-in-c-e8a0f63161b7?source=rss-dab3141711d6------2</link>
            <guid isPermaLink="false">https://medium.com/p/e8a0f63161b7</guid>
            <category><![CDATA[event-delegation]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[realtime]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Full Stack Content Creator]]></dc:creator>
            <pubDate>Mon, 24 Apr 2023 06:35:44 GMT</pubDate>
            <atom:updated>2023-04-24T16:58:00.975Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1019/1*ycXXRNYuWNgO3MGWhiYa-w.jpeg" /></figure><h3>A Comprehensive Guide with Real-World Examples</h3><p>Introduction:In today’s software development landscape, event-driven programming has become a crucial paradigm for handling asynchronous tasks efficiently. C# provides powerful features called events and delegates that enable developers to implement event-driven programming effectively. In this comprehensive blog post, we will delve into the world of events and delegates in C#, understand their core concepts, explore various usage scenarios, advantages, disadvantages, and real-world examples to illustrate their practical applications.</p><p><strong>Table of Contents:</strong></p><ol><li>Introduction</li><li>What are Delegates in C#?</li></ol><ul><li>Delegate Basics</li><li>Usage Scenarios</li><li>Advantages and Disadvantages</li><li>Real-World Example</li></ul><p>3. What are Events in C#?</p><ul><li>Event Basics</li><li>Usage Scenarios</li><li>Advantages and Disadvantages</li><li>Real-World Example</li></ul><p>4. Combining Delegates and Events</p><ul><li>Delegate Chaining</li><li>Handling Multiple Events</li></ul><p>5. Advanced Topics</p><ul><li>Anonymous Methods</li><li>Lambda Expressions</li><li>Generic Delegates</li><li>Custom Delegates</li></ul><p>6. Best Practices and Tips</p><ul><li>Proper Use of Events and Delegates</li><li>Memory Management</li><li>Exception Handling</li><li>Debugging Tips</li></ul><p>7. Conclusion</p><h4><strong>What are Delegates in C#?</strong></h4><p><strong>Delegate Basics</strong>: Delegates in C# are type-safe function pointers that refer to methods with specific signatures. They allow methods to be assigned to delegate objects and called at runtime. A delegate is declared using the delegate keyword, followed by the return type, delegate name, and the parameter list in parentheses. Delegates can have different types, depending on the method signatures they can point to.</p><p><strong>Usage Scenarios:</strong> Delegates are widely used in scenarios such as event handling, callback functions, and asynchronous programming. For example, consider a scenario where a math calculator needs to perform arithmetic operations:</p><pre>public delegate double CalculatorDelegate(double a, double b);<br><br>public class Calculator<br>{<br>    public static double Add(double a, double b)<br>    {<br>        return a + b;<br>    }<br><br>    public static double Subtract(double a, double b)<br>    {<br>        return a - b;<br>    }<br><br>    public static double Multiply(double a, double b)<br>    {<br>        return a * b;<br>    }<br><br>    public static double Divide(double a, double b)<br>    {<br>        return a / b;<br>    }<br>}</pre><p>In this example, we define a CalculatorDelegate delegate that references methods for arithmetic operations. We can use this delegate to perform arithmetic operations dynamically at runtime by assigning different methods to it.</p><h4>Advantages and Disadvantages of Delegates:</h4><p>Delegates offer several advantages, including:</p><ol><li><strong>Flexibility</strong>: Delegates allow methods to be assigned to delegate objects and called at runtime, making them highly flexible and dynamic.</li><li><strong>Code Reusability</strong>: Delegates promote code reusability by allowing multiple methods with the same signature to be assigned to the same delegate, enabling different implementations for the same functionality.</li><li><strong>Separation of Concerns</strong>: Delegates facilitate the separation of concerns by allowing the decoupling of event publishers and subscribers, ensuring loose coupling between components.</li></ol><p>However, delegates also have some disadvantages, including:</p><ol><li><strong>Complexity</strong>: Delegates can introduce complexity to code due to their dynamic nature and potential for multiple methods to be assigned to the same delegate.</li><li><strong>Performance Overhead</strong>: Delegates may introduce a performance overhead due to the dynamic invocation of methods at runtime.</li><li><strong>Memory Management</strong>: Delegates can cause memory leaks if not properly handled, as they hold references to the methods they point to.</li></ol><h4>Real-World Example:</h4><p>Let’s consider a real-world example of a stock market application that uses delegates for event handling. In this scenario, the application has a Stock class that represents a stock with properties such as Symbol, Price, and ChangePercentage. The application also has a StockMarket class that is responsible for updating the stock prices and notifying the subscribers when the stock prices change.</p><pre>public class Stock<br>{<br>    public string Symbol { get; set; }<br>    public decimal Price { get; set; }<br>    public decimal ChangePercentage { get; set; }<br>}<br><br>public class StockMarket<br>{<br>    private List&lt;Stock&gt; stocks = new List&lt;Stock&gt;();<br>    public delegate void StockPriceChangedEventHandler(object sender, Stock stock);<br>    public event StockPriceChangedEventHandler StockPriceChanged;<br><br>    public void AddStock(string symbol, decimal price)<br>    {<br>        var stock = new Stock { Symbol = symbol, Price = price, ChangePercentage = 0 };<br>        stocks.Add(stock);<br>    }<br><br>    public void UpdateStockPrice(string symbol, decimal newPrice)<br>    {<br>        var stock = stocks.FirstOrDefault(s =&gt; s.Symbol == symbol);<br>        if (stock != null)<br>        {<br>            var oldPrice = stock.Price;<br>            stock.Price = newPrice;<br>            stock.ChangePercentage = ((newPrice - oldPrice) / oldPrice) * 100;<br><br>            // Raise the event to notify subscribers<br>            OnStockPriceChanged(this, stock);<br>        }<br>    }<br><br>    protected virtual void OnStockPriceChanged(object sender, Stock stock)<br>    {<br>        // Check if there are any subscribers to the event<br>        StockPriceChanged?.Invoke(sender, stock);<br>    }<br>}</pre><p>In this example, the StockMarket class uses a delegate StockPriceChangedEventHandler and an event StockPriceChanged to handle stock price changes. The StockPriceChanged event is raised whenever the UpdateStockPrice method is called, notifying the subscribers with the updated stock object.</p><p><strong>Usage of Delegates in the Example</strong>:</p><ul><li>The StockPriceChangedEventHandler delegate is used to define the signature of the event handler method that will be called when the StockPriceChanged event is raised.</li><li>The event keyword is used to define the StockPriceChanged event, which is a mechanism for subscribers to register their event handler methods to be called when the event is raised.</li><li>The OnStockPriceChanged method is used to raise the StockPriceChanged event and invoke the registered event handler methods.</li></ul><p><strong>Advantages of Delegates in the Example</strong>:</p><ul><li>Flexibility: Delegates allow dynamic event handling, where subscribers can register their event handler methods at runtime, providing flexibility in managing event subscriptions.</li><li>Code Reusability: Delegates enable multiple subscribers to register their event handler methods to the same event, allowing for code reusability and extensibility.</li><li>Separation of Concerns: Delegates help to decouple the event publisher (StockMarket class) from the event subscribers (subscribers&#39; event handler methods), promoting separation of concerns and maintainability of the code.</li></ul><p><strong>Disadvantages of Delegates in the Example</strong>:</p><ul><li>Complexity: Delegates introduce complexity in managing event subscriptions and handling event invocation, which may require additional effort for debugging and maintenance.</li><li>Performance Overhead: Delegates may introduce a performance overhead due to the dynamic invocation of event handler methods at runtime, especially when multiple event handlers are involved.</li><li>Memory Management: Delegates may hold references to event subscribers, which can cause memory leaks if not properly managed, as the subscribers may not be garbage collected.</li></ul><h4>What are Events in C#?</h4><p>Event Basics: Events in C# are a special type of delegate that provides a standardized way of declaring, raising, and handling events. Events are based on delegates and provide a more controlled way of handling event subscriptions and invocations. Events are used to notify objects (event subscribers) when an action or an occurrence (event) happens in another object (event publisher).</p><p><strong>Events have the following key characteristics</strong>:</p><ol><li>Event Publisher: The object that raises an event is called the event publisher. In the previous example, the StockMarket class is the event publisher as it raises the StockPriceChanged event.</li><li>Event Subscriber: The object that handles an event is called the event subscriber. In the previous example, any object that subscribes to the StockPriceChanged event by registering its event handler method is an event subscriber.</li><li>Event Handler: The method that is registered to handle an event is called the event handler. In the previous example, the StockPriceChangedEventHandler delegate is used to define the signature of the event handler method that will be called when the StockPriceChanged event is raised.</li><li>Event Declaration: Events are declared using the event keyword followed by the delegate type that defines the event handler method signature. In the previous example, the StockPriceChanged event is declared using the StockPriceChangedEventHandler delegate.</li><li>Event Subscription: Objects can subscribe to events by registering their event handler methods to the event using the += operator. In the previous example, the event handler methods are registered to the StockPriceChanged event using the += operator.</li><li>Event Invocation: Events are raised using the Invoke method of the event delegate or by simply calling the event like a method. In the previous example, the StockPriceChanged event is raised by invoking the StockPriceChanged delegate using the OnStockPriceChanged method.</li><li>Event Unsubscription: Objects can unsubscribe from events by unregistering their event handler methods from the event using the -= operator. In the previous example, the event handler methods can be unregistered from the StockPriceChanged event using the -= operator.</li></ol><p>Now let’s take a look at an example scenario where events and delegates can be used in a real-time application.</p><p>Imagine you are building a chat application that allows users to send messages to each other in real-time. You have a ChatServer class that is responsible for handling incoming messages and notifying the subscribers when new messages arrive. The ChatServer class has a MessageReceived event that is raised whenever a new message is received. Users can subscribe to this event to be notified when a new message arrives.</p><pre>public class ChatServer<br>{<br>    public delegate void MessageReceivedEventHandler(object sender, MessageEventArgs e);<br>    public event MessageReceivedEventHandler MessageReceived;<br><br>    public void ReceiveMessage(string sender, string message)<br>    {<br>        // Process the incoming message and raise the event<br>        var messageEventArgs = new MessageEventArgs(sender, message);<br>        OnMessageReceived(this, messageEventArgs);<br>    }<br><br>    protected virtual void OnMessageReceived(object sender, MessageEventArgs e)<br>    {<br>        // Check if there are any subscribers to the event<br>        MessageReceived?.Invoke(sender, e);<br>    }<br>}<br><br>public class MessageEventArgs : EventArgs<br>{<br>    public string Sender { get; }<br>    public string Message { get; }<br><br>    public MessageEventArgs(string sender, string message)<br>    {<br>        Sender = sender;<br>        Message = message;<br>    }<br>}</pre><p>In this example, the ChatServer class uses a delegate MessageReceivedEventHandler and an event MessageReceived to handle incoming messages. The MessageReceived event is raised whenever a new message is received, notifying the subscribers with the sender and message information.</p><p><strong>Usage of Delegates in the Example:</strong></p><ul><li>The MessageReceivedEventHandlerdelegate is used to define the signature of the event handler method that will be called when theMessageReceived` event is raised.</li></ul><p><strong>Usage of Events in the Example</strong>:</p><ul><li>The MessageReceived event is declared using the MessageReceivedEventHandler delegate, which defines the signature of the event handler method for handling incoming messages.</li><li>Subscribers can register their event handler methods to the MessageReceived event using the += operator, and unregister them using the -= operator.</li><li>The MessageReceived event is raised by invoking the MessageReceived delegate using the OnMessageReceived method, which notifies all subscribers with the sender and message information.</li></ul><p>Now, let’s see how this chat application scenario demonstrates the advantages of using events and delegates in C#.</p><p><strong>Advantages of Events and Delegates:</strong></p><ol><li>Loose Coupling: Events and delegates allow for loose coupling between objects in a C# application. In the chat application example, the ChatServer class does not need to know about the subscribers or how they handle incoming messages. It simply raises the MessageReceived event, and any registered subscribers&#39; event handler methods will be called. This allows for flexibility and easy maintenance, as changes in the event publisher do not directly affect the event subscribers.</li><li>Extensibility: Events and delegates provide a way to extend the functionality of an application without modifying existing code. In the chat application example, new subscribers can easily register their event handler methods to the MessageReceived event without modifying the ChatServer class. Similarly, event subscribers can be removed without affecting the event publisher. This promotes code reusability and scalability.</li><li>Multiple Subscribers: Events and delegates allow for multiple subscribers to handle an event. In the chat application example, multiple users can subscribe to the MessageReceived event and receive notifications when new messages arrive. This enables a one-to-many communication pattern, where a single event can be handled by multiple objects.</li><li>Clear Separation of Concerns: Events and delegates help in separating the concerns of different parts of an application. In the chat application example, the ChatServer class is responsible for handling incoming messages, and the event subscribers are responsible for handling the received messages according to their specific logic. This promotes better code organization and maintainability.</li><li>Encapsulation: Events and delegates encapsulate the event handling logic in a separate class or method. In the chat application example, the event handling logic is encapsulated in the event handler methods of the subscribers, which allows for better encapsulation and abstraction of the event handling logic.</li></ol><p><strong>Disadvantages of Events and Delegates:</strong></p><ol><li>Complexity: Events and delegates can introduce complexity in the code, especially when dealing with multiple events and subscribers. Care must be taken to properly manage event subscriptions, unsubscriptions, and event invocations to avoid potential issues like memory leaks or event handling order.</li><li>Overhead: Events and delegates can introduce overhead in terms of performance and memory usage. Invoking events and handling them requires additional processing compared to direct method calls. However, the overhead is usually negligible in most scenarios and the benefits of using events and delegates usually outweigh the costs.</li></ol><p>In conclusion, events and delegates are powerful tools in C# that provide a robust and flexible way to handle events and notifications in an object-oriented application. They promote loose coupling, extensibility, and encapsulation, making the code more maintainable and scalable. However, they should be used judiciously, considering the potential complexity and overhead they may introduce. By understanding the concepts of events and delegates and their usage in real-time scenarios like the chat application example, developers can leverage them effectively in their C# applications to achieve efficient event-driven programming.</p><h4>Combining Delegates and Events:</h4><p>Delegates in C# can be combined to form multicast delegates, which can be used to invoke multiple methods sequentially or concurrently. This allows for powerful event handling scenarios where multiple subscribers can handle an event in a specific order or simultaneously.</p><p><strong>Example</strong>: Let’s consider an online auction system where multiple bidders can bid on an item. We can use a multicast delegate to handle the bidding process. The auctioneer can define a delegate that represents the bidding action, and bidders can register their methods as event handlers to this delegate. When the auctioneer raises the bidding event, all registered methods will be invoked in the order they were registered, allowing multiple bidders to bid on the item simultaneously.</p><pre>using System;<br><br>public delegate void BiddingHandler(string bidderName, decimal bidAmount);<br><br>public class Auctioneer<br>{<br>    public event BiddingHandler BiddingEvent;<br><br>    public void RaiseBiddingEvent(string bidderName, decimal bidAmount)<br>    {<br>        if (BiddingEvent != null)<br>        {<br>            BiddingEvent(bidderName, bidAmount);<br>        }<br>    }<br>}<br><br>public class Bidder<br>{<br>    public string Name { get; }<br><br>    public Bidder(string name)<br>    {<br>        Name = name;<br>    }<br><br>    public void PlaceBid(string itemName, decimal bidAmount)<br>    {<br>        Console.WriteLine($&quot;{Name} placed a bid of {bidAmount} on {itemName}&quot;);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Auctioneer auctioneer = new Auctioneer();<br>        Bidder bidder1 = new Bidder(&quot;Bidder1&quot;);<br>        Bidder bidder2 = new Bidder(&quot;Bidder2&quot;);<br><br>        // Register event handlers<br>        auctioneer.BiddingEvent += bidder1.PlaceBid;<br>        auctioneer.BiddingEvent += bidder2.PlaceBid;<br><br>        // Raise the event<br>        auctioneer.RaiseBiddingEvent(&quot;Item1&quot;, 100);<br>    }<br>}</pre><h4>Handling Multiple Events:</h4><p>In some scenarios, an object may need to handle multiple events from different sources. C# provides a simple way to handle multiple events using the “+=” operator to attach event handlers for different events to the same delegate.</p><p>Example: In a multimedia player application, an object may need to handle events from different media sources, such as video playback, audio playback, and subtitle display. The object can define a delegate that represents the actions for these events, and multiple media sources can register their event handlers to this delegate using the “+=” operator. When any of the media sources raise an event, the registered event handlers will be invoked accordingly.</p><pre>using System;<br><br>public class MediaPlayer<br>{<br>    public event EventHandler VideoPlaybackEvent;<br>    public event EventHandler AudioPlaybackEvent;<br>    public event EventHandler SubtitleDisplayEvent;<br><br>    public void PlayVideo(string videoName)<br>    {<br>        Console.WriteLine($&quot;Playing video: {videoName}&quot;);<br>        VideoPlaybackEvent?.Invoke(this, EventArgs.Empty);<br>    }<br><br>    public void PlayAudio(string audioName)<br>    {<br>        Console.WriteLine($&quot;Playing audio: {audioName}&quot;);<br>        AudioPlaybackEvent?.Invoke(this, EventArgs.Empty);<br>    }<br><br>    public void DisplaySubtitle(string subtitle)<br>    {<br>        Console.WriteLine($&quot;Displaying subtitle: {subtitle}&quot;);<br>        SubtitleDisplayEvent?.Invoke(this, EventArgs.Empty);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        MediaPlayer mediaPlayer = new MediaPlayer();<br><br>        // Register event handlers for different events<br>        mediaPlayer.VideoPlaybackEvent += (sender, e) =&gt; Console.WriteLine(&quot;Video playback event&quot;);<br>        mediaPlayer.AudioPlaybackEvent += (sender, e) =&gt; Console.WriteLine(&quot;Audio playback event&quot;);<br>        mediaPlayer.SubtitleDisplayEvent += (sender, e) =&gt; Console.WriteLine(&quot;Subtitle display event&quot;);<br><br>        // Raise different events<br>        mediaPlayer.PlayVideo(&quot;Video1&quot;);<br>        mediaPlayer.PlayAudio(&quot;Audio1&quot;);<br>        mediaPlayer.DisplaySubtitle(&quot;Subtitle1&quot;);<br>    }<br>}</pre><h4>Advanced Topics:</h4><p><strong>Anonymous Methods</strong>: C# allows defining anonymous methods, which are nameless methods that can be used as event handlers. Anonymous methods provide a concise way to define small, inline event handler methods without explicitly declaring a separate method. Anonymous methods can be useful in scenarios where the event handler logic is short and simple.</p><p><strong>Example</strong>: In a button click event handler, instead of declaring a separate method for the event handler, an anonymous method can be defined directly inside the event handler registration code. This can make the code more concise and easier to read, especially for short event handler logic.</p><pre>using System;<br><br>public class Button<br>{<br>    public event EventHandler Click;<br><br>    public void OnClick()<br>    {<br>        Click?.Invoke(this, EventArgs.Empty);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button button = new Button();<br><br>        // Register event handler using anonymous method<br>        button.Click += (sender, e) =&gt;<br>        {<br>            Console.WriteLine(&quot;Button clicked&quot;);<br>        };<br><br>        // Raise the event<br>        button.OnClick();<br>    }<br>}</pre><p><strong>Lambda</strong> <strong>Expressions</strong>: Lambda expressions are another way to define inline event handler methods in C#. Lambda expressions are concise and provide a convenient way to define event handlers using a functional programming approach. Lambda expressions can be used with delegates and events to provide compact and expressive event handling code.</p><p><strong>Example</strong>: Instead of defining an anonymous method as an event handler, a lambda expression can be used to define the event handler directly in the event registration code. This can make the code more concise and expressive, especially for small event handling logic.</p><pre>using System;<br><br>public class Button<br>{<br>    public event EventHandler Click;<br><br>    public void OnClick()<br>    {<br>        Click?.Invoke(this, EventArgs.Empty);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button button = new Button();<br><br>        // Register event handler using lambda expression<br>        button.Click += (sender, e) =&gt; Console.WriteLine(&quot;Button clicked&quot;);<br><br>        // Raise the event<br>        button.OnClick();<br>    }<br>}</pre><p><strong>Generic Delegates</strong>: C# provides generic delegates that can be used with different types of event handlers. Generic delegates allow for more flexibility and type safety in event handling scenarios where the event handlers may have different parameter types or return types.</p><p><strong>Example</strong>: Instead of using a specific delegate type for a specific event, a generic delegate can be used to handle events with different parameter types, such as EventHandler&lt;TEventArgs&gt;. This allows for more reusable event handling code that can handle events with different event arguments.</p><pre>using System;<br><br>public delegate void Action&lt;T&gt;(T arg);<br><br>public class Button&lt;T&gt;<br>{<br>    public event Action&lt;T&gt; Click;<br><br>    public void OnClick(T data)<br>    {<br>        Click?.Invoke(data);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Button&lt;int&gt; button1 = new Button&lt;int&gt;();<br>        Button&lt;string&gt; button2 = new Button&lt;string&gt;();<br><br>        // Register event handler for int type<br>        button1.Click += (data) =&gt; Console.WriteLine($&quot;Button clicked with data: {data}&quot;);<br><br>        // Register event handler for string type<br>        button2.Click += (data) =&gt; Console.WriteLine($&quot;Button clicked with data: {data}&quot;);<br><br>        // Raise events with different data types<br>        button1.OnClick(10);<br>        button2.OnClick(&quot;Hello&quot;);<br>    }<br>}</pre><p><strong>Custom Delegates</strong>: In addition to the built-in delegates in C#, developers can define their own custom delegates to represent event handlers with specific signatures. Custom delegates can provide more descriptive and type-safe event handling code, especially in complex scenarios where the event handlers have specific requirements.</p><p><strong>Example</strong>: In a custom logging framework, a custom delegate with a specific signature can be defined to represent the logging action, such as LogEventHandler. Event handlers can then be registered using this custom delegate, providing a more descriptive and type-safe way to handle logging events.</p><pre>using System;<br><br>public delegate void CalculationHandler(int num1, int num2);<br><br>public class Calculator<br>{<br>    public event CalculationHandler CalculationEvent;<br><br>    public void Add(int num1, int num2)<br>    {<br>        int result = num1 + num2;<br>        CalculationEvent?.Invoke(num1, num2);<br>        Console.WriteLine($&quot;Addition result: {result}&quot;);<br>    }<br><br>    public void Subtract(int num1, int num2)<br>    {<br>        int result = num1 - num2;<br>        CalculationEvent?.Invoke(num1, num2);<br>        Console.WriteLine($&quot;Subtraction result: {result}&quot;);<br>    }<br>}<br><br>class Program<br>{<br>    static void Main(string[] args)<br>    {<br>        Calculator calculator = new Calculator();<br><br>        // Register event handler<br>        calculator.CalculationEvent += (num1, num2) =&gt; Console.WriteLine($&quot;Calculation performed with {num1} and {num2}&quot;);<br><br>        // Perform calculations<br>        calculator.Add(5, 3);<br>        calculator.Subtract(10, 7);<br>    }<br>}</pre><h4>Best Practices and Tips:</h4><p><strong>Proper Use of Events and Delegates</strong>: It’s important to use events and delegates appropriately in the right scenarios. Events should be used for notifications or notifications of changes, while delegates can be used for callbacks or function pointers.</p><ul><li>Define delegates with appropriate signature matching the methods that will be subscribed to them.</li><li>Use the event keyword to declare events, which ensures that the event can only be subscribed to and unsubscribed from within the declaring class.</li><li>Use protected virtual methods to raise events, allowing derived classes to override and extend the behavior of event invocation.</li><li>Always check for null before invoking an event to avoid null reference exceptions.</li></ul><pre>public class MyClass<br>{<br>    // Declare an event using the event keyword<br>    public event EventHandler MyEvent;<br><br>    // Method to raise the event<br>    protected virtual void OnMyEvent(EventArgs e)<br>    {<br>        MyEvent?.Invoke(this, e);<br>    }<br>}</pre><p><strong>Memory Management:</strong></p><ul><li>Be cautious with long-lived events that can cause memory leaks. Always unsubscribe from events when they are no longer needed, especially in cases where the subscriber has a longer lifespan than the publisher.</li><li>Use weak event pattern or weak references to prevent event handlers from preventing garbage collection of objects.</li></ul><pre>public class Button<br>{<br>    // Declare a weak event using WeakEventManager<br>    private WeakEventManager&lt;Button, EventArgs&gt; _clickEventManager = new WeakEventManager&lt;Button, EventArgs&gt;();<br><br>    // Declare an event for button click<br>    public event EventHandler Click<br>    {<br>        add =&gt; _clickEventManager.AddEventHandler(this, value);<br>        remove =&gt; _clickEventManager.RemoveEventHandler(this, value);<br>    }<br><br>    // Method to raise the Click event<br>    public void OnClick()<br>    {<br>        _clickEventManager.HandleEvent(this, EventArgs.Empty, nameof(Click));<br>    }<br>}</pre><p><strong>Exception Handling:</strong></p><ul><li>Handle exceptions appropriately in event handlers to prevent crashing the application.</li><li>Use try-catch blocks within event handlers to catch and handle any exceptions that may occur.</li></ul><pre>private void Button_Click(object sender, EventArgs e)<br>{<br>    try<br>    {<br>        // Code that may throw exceptions<br>    }<br>    catch (Exception ex)<br>    {<br>        // Handle the exception<br>        Console.WriteLine($&quot;An exception occurred: {ex.Message}&quot;);<br>    }<br>}</pre><p><strong>Debugging Tips:</strong></p><ul><li>Use event handlers’ stack trace and call stack information to identify the source of an event.</li><li>Utilize debugger breakpoints and watches to track the flow of events and delegate invocations.</li></ul><pre>private void Button_Click(object sender, EventArgs e)<br>{<br>    // Use debugger breakpoints to track the flow of events<br>    Console.WriteLine(&quot;Button_Click is called&quot;);<br>}</pre><h4>Conclusion:</h4><p>Events and delegates are powerful features in C# that provide a way to implement event-driven programming and enable loose coupling between components. Proper use of events and delegates can lead to cleaner and more maintainable code. By following best practices, handling memory management, exception handling, and utilizing debugging tips, you can ensure effective usage of events and delegates in your C# applications.</p><p>I hope this detailed blog post on events and delegates in C# with examples and best practices has been helpful to you. Remember to apply these concepts wisely in your code and make use of the code examples provided to enhance your understanding. Happy coding!</p><p>Please let me know your thoughts on this story by clapping or leaving a comment with suggestions for future topics.</p><p>Let’s connect on <a href="https://lnkd.in/dC3wiHUw">Instagram</a> and <a href="https://www.linkedin.com/in/rupa-sri-091b74117/">LinkedIn</a> and don’t forget to follow me here on Medium for more content.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8a0f63161b7" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>