Friday, 30 December 2022

Stack and Heap Memory in C# with Examples

 In this article, I am going to discuss Stack and Heap Memory in C# Application with Examples. Please read our previous article, where we discussed the Checked and Unchecked Keywords in C# with Examples. As part of this article, first, we will discuss what happens internally when we declare a variable of value types as well as reference types. Then we will move forward and learn two important concepts i.e. stack and heap memory as well as we will talk about value types and reference types.

What happens internally when we declare a variable in .NET Application?

When we declare a variable in a .NET application, it allocates some memory in the RAM. The memory that it allocates in RAM has three things are as follows:

  1. Name of the variable,
  2. The data type of the variable, and
  3. Value of the variable.

For better understanding, please have a look at the following image. Here, we declare a variable of type int and assign a value 101.

What happens internally when we declare a variable in .NET Application?

The above image shows a high-level overview of what happening in the memory. But depending on the data type (i.e. depending on the value type and reference type ), the memory may be allocated either in the stack or in the heap memory.

Understanding Stack and Heap Memory in C#:

There are two types of memory allocation for the variables that we created in the .NET Application i.e. stack memory and heap memory. Let us understand the stack and heap memory with an example. In order to understand stack and heap, please have a look at the following code, and let’s understand what actually happens in the below code internally.

Understanding Stack and Heap Memory in .NET

As you can see in the above image, the SomeMethod has three statements, let’s understand statement by statement how things are executed internally.

Statement1:

When the first statement is executed, the compiler allocates some memory in the stack. The stack memory is responsible for keeping track of the running memory needed in your application. For better understanding, please have a look at the following image.

Stack in .NET Application with Examples

Statement2:

When the second statement is executed, it stacks this memory allocation (memory allocation for variable y) on top of the first memory allocation (memory allocation for variable x). You can think about the stack as a series of plates or dishes put on top of each other. Please have a look at the following diagram for a better understanding.

Stack memory in C#

The Stack Memory allocation and de-allocation in .NET are done using the Last In First Out principle. In other words, we can say that the memory allocation and de-allocation are done only at one end of the memory, i.e., the top of the stack.

Statement3:

In the 3rd statement, we have created an object of SomeClass. When the 3rd statement is executed, it internally creates a pointer on the stack memory and the actual object is stored in a different memory location called Heap memory. The heap memory location does not track running memory. Heap is used for dynamic memory allocation. For a better understanding please have a look at the below image.

Heap Memory in .NET Application

Note: The reference pointers are allocated on the stack. The statement, SomeClass cls1 does not allocate any memory for an instance of SomeClass, it only allocates a variable with the name cls1 in the stack and sets its value to null. The time it hits the new keyword, it allocates memory in the heap.

What happens when the method completes its execution?

When the three statements are executed, then the control will exit from the method. When it passes the end control i.e. the end curly brace “}”, it will clear all the memory variables which are created on the stack. It will de-allocate the memory in a ‘LIFO’ fashion from the stack. For a better understanding please have a look at the below image.

What happens to stack and Heap memory when the method complete its execution?

It will not de-allocate the heap memory. Later, the heap memory will be de-allocated by the garbage collector. Now you may have one question in your mind why two types of memory, can’t we just allocate everything to just one memory type?

Why do we have two types of memory?

As we know, in C#, the primitive data types such as int, double, bool, etc. just hold a single value. On the other hand, the reference data types or object data types are complex i.e. an object data type or reference data type can have reference to other objects as well as other primitive data types.

So, the reference data type holds references to other multiple values, and each one of them must be stored in memory. Object types need dynamic memory while primitive data types need static memory. Please have a look at the following image for a better understanding.

Why we have two types of memory (Stack and Heap in .NET)?

Value types and reference types in .NET

As we understood the concept of Stack and Heap, Now, let us move forward and understand the concept value types and reference types in detail. The Value types are the types that hold both data and memory in the same location. On the other hand, a reference type is a type that has a pointer that points to the actual memory location.

Understanding Value Type in C#:

Let us understand value type with an example. Please have a look at the following image. As you can see in the image, first we create an integer variable with the name x and then we assign this x integer value to another integer variable whose name is y. In this case, the memory allocation for these two variables will be done inside the stack memory.

Understanding Value Type in .NET

In .NET, when we assign one integer variable value to another integer variable, then it creates a completely different copy in the stack memory that’s what you can see in the above image. So, if you change one variable value, then the other variable will not be affected. In .NET these kinds of data types are called ‘Value types’. So, bool, byte, char, decimal, double, enum, float, long, sbyte, int, short, ulong, struct, uint, ushort are examples of value types.

Understanding Reference Type in C#:

Let us understand reference type with an example. Please have a look at the following image. Here, first, we create an object i.e. obj1) and then assign this object to another object i.e. obj2. In this case, both reference variables (obj1 and obj2) will point to the same memory location.

Understanding Reference Type in C#

In this case, when you change one of them, the other object is also gets affected. These kinds of data types are termed as ‘Reference types’ in .NET. So, class, interface, object, string, and delegate are examples of Reference Types.

How is the heap memory freed up?

The memory allocation which is done on the stack is gone when the control moves out from the method i.e once the method completes its execution. On the other hand, the memory allocation which is done on the heap needs to be de-allocated by the garbage collector.

When an object stored on the heap is no longer used, that means the object does not have any reference pointing, then the object is eligible for garbage collection. At some point in time, the garbage collector will de-allocate this object from the heap.

In the next article, I am going to discuss Boxing and Unboxing in C#.NET with Examples. Here, in this article, I try to explain Stack and Heap Memory in C# with Examples. I hope you enjoy this Stack and Heap Memory in C# with Examples article. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Print no of character from string

  string str = "idempotent";


            Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();


            char[] strChar = str.ToCharArray();

            foreach(char c in strChar)

            {

                 

              if(keyValuePairs.Where(x=>x.Key==c.ToString()).Any())

                {

                    keyValuePairs[c.ToString()] = keyValuePairs[c.ToString()] + 1;

                    

                }

              else

                {

                    keyValuePairs.Add(c.ToString(), 1);


                }

            }


            

              foreach(KeyValuePair<string,int> k in keyValuePairs)

            {

                Console.WriteLine(k.Value);

            }

Wednesday, 28 December 2022

Method Overloading And Method Overriding In C#

 Polymorphism means “Many Forms”. In Polymorphism, poly means “Many” and morph means “Forms.” Polymorphism is one of the main pillars in Object Oriented Programming. It allows you to create multiple methods with the same name but different signatures in the same class. The same name methods can also be in derived classes.

 
There are two types of Polymorphism,
  1. Method Overloading
  2. Method Overriding
In this article, I will explain method overloading and method overriding concept in C#. I will try to demonstrate step by step differences between these.
 

Method Overloading

Method Overloading is a type of polymorphism. It has several names like “Compile Time Polymorphism” or “Static Polymorphism” and sometimes it is called “Early Binding”.
 
Method Overloading means creating multiple methods in a class with same names but different signatures (Parameters). It permits a class, struct, or interface to declare multiple methods with the same name with unique signatures.
 
Compiler automatically calls required method to check number of parameters and their type which are passed into that method.
  1. using System;  
  2. namespace DemoCsharp  
  3. {  
  4.     class Program  
  5.     {  
  6.         public int Add(int num1, int num2)  
  7.         {  
  8.             return (num1 + num2);  
  9.         }  
  10.         public int Add(int num1, int num2, int num3)  
  11.         {  
  12.             return (num1 + num2 + num3);  
  13.         }  
  14.         public float Add(float num1, float num2)  
  15.         {  
  16.             return (num1 + num2);  
  17.         }  
  18.         public string Add(string value1, string value2)  
  19.         {  
  20.             return (value1 + " " + value2);  
  21.         }  
  22.         static void Main(string[] args)  
  23.         {  
  24.             Program objProgram = new Program();  
  25.             Console.WriteLine("Add with two int parameter :" + objProgram.Add(3, 2));  
  26.             Console.WriteLine("Add with three int parameter :" + objProgram.Add(3, 2, 8));  
  27.             Console.WriteLine("Add with two float parameter :" + objProgram.Add(3 f, 22 f));  
  28.             Console.WriteLine("Add with two string parameter :" + objProgram.Add("hello""world"));  
  29.             Console.ReadLine();  
  30.         }  
  31.     }  
  32. }  
In the above example, you can see that there are four methods with same name but type of parameters or number of parameters is different. When you call Add(4,5), complier automatically calls the method which has two integer parameters and when you call Add(“hello”,”world”), complier calls the method which has two string parameters. So basically in method overloading complier checks which method should be called at the time of compilation.
 
Note: Changing the return type of method does not make the method overloaded. You cannot create method overloaded vary only by return type.
 

Method Overriding

 
Method Overriding is a type of polymorphism. It has several names like “Run Time Polymorphism” or “Dynamic Polymorphism” and sometime it is called “Late Binding”. 
 
Method Overriding means having two methods with same name and same signatures [parameters], one should be in the base class and other method should be in a derived class [child class]. You can override the functionality of a base class method to create a same name method with same signature in a derived class. You can achieve method overriding using inheritance. Virtual and Override keywords are used to achieve method overriding.
  1. using System;  
  2. namespace DemoCsharp  
  3. {  
  4.     class BaseClass  
  5.     {  
  6.         public virtual int Add(int num1, int num2)  
  7.         {  
  8.             return (num1 + num2);  
  9.         }  
  10.     }  
  11.     class ChildClass: BaseClass  
  12.     {  
  13.         public override int Add(int num1, int num2)  
  14.         {  
  15.             if (num1 <= 0 || num2 <= 0)  
  16.             {  
  17.                 Console.WriteLine("Values could not be less than zero or equals to zero");  
  18.                 Console.WriteLine("Enter First value : ");  
  19.                 num1 = Convert.ToInt32(Console.ReadLine());  
  20.                 Console.WriteLine("Enter First value : ");  
  21.                 num2 = Convert.ToInt32(Console.ReadLine());  
  22.             }  
  23.             return (num1 + num2);  
  24.         }  
  25.     }  
  26.     class Program  
  27.     {  
  28.         static void Main(string[] args)  
  29.         {  
  30.             BaseClass baseClassObj;  
  31.             baseClassObj = new BaseClass();  
  32.             Console.WriteLine("Base class method Add :" + baseClassObj.Add(-3, 8));  
  33.             baseClassObj = new ChildClass();  
  34.             Console.WriteLine("Child class method Add :" + baseClassObj.Add(-2, 2));  
  35.             Console.ReadLine();  
  36.         }  
  37.     }  
  38. }  
In the above example, I have created two same name methods in the BaseClass as well as in the ChildClass. When you call the BaseClass Add method with less than zero value as parameters then it adds successfully. But when you call the ChildClass Add method with less than zero value then it checks for negative value. And the passing values are negative then it asks for new value.
 
So, here it is clear that we can modify the base class methods in derived classes.
 
Points to be remembered,
  1. Method cannot be private.
  2. Only abstract or virtual method can be overridden.
  3. Which method should be called is decided at run time.

Recent Post

how to control duplicate order