Introduction
As we know, there could be many ways to optimize the performance of code, and choosing the correct data type is one of them. In this blog, I will show you some reasons for it.
Let’s start with the memory type defined by CLR in C#.
In .NET, we actually don’t need to think much about memory management thanks to GC(Garbage Collector) in .NET Framework.
Garbage Collector manages the allocation and releases memory for an application.
CLR allocates memory in Stack and Heap. Before we start with stack and heap in depth let me introduce two more important things in .NET Framework and those are Value Type Variables and Reference Type Variables.
Examples of Value Type Variables: bool, byte, char, decimal, double, float, int, long, uint, ulong, ushort,enum, struct.
Examples of Reference Type Variables:- Class, interface, string, delegate, object, dynamic, arrays.
Wait a minute, what string is doing in under Reference Type Variables? Why it is not under Value Type Variables as char?
Stack is simple. First-In-Last-Out memory structure and is highly efficient and Heap can be called a random jumble of objects. Its advantage is that it allows objects to be allocated or deallocated in random order.
Now, Stack always stores two things first reference portion of reference-typed local variables and parameters and second Value-typed local variables and method parameters.
Whereas Heap stores the content of reference-type objects and anything structured inside a reference-type object.
As we know Int has a fixed memory size so it could be saved in Stack, so stack store fixed memory size variables in it. And, the string could be of any size that is the reason it does not have a pre-defined memory size and it could be very large. That is the reason it’s in Reference type variables as it requires dynamic memory allocation.
If you assign a value type variables to another variable, the value is copied directly but in case of reference type the reference is copied and both variables point to the same location of the heap.
Based on requirements you need to select variables specifically. For example, your code could be executed by using any positive number then you must use uint instead of int and it’s always best to avoid the use of local variables instead we can call a method directly into the final expression to avoid intermediate memory locations.
If possible then make use of the struct, as it works faster compare to class, Use Array instead of List, remove variables whose values are not in used.
- public class Employee {
- public int Id {
- get;
- set
- }
- public string Name {
- get;
- set;
- }
- }
- public class Main {
- List < Employee > employees = new List < Employee > ();
- employees = EmployeeData.All();
- }
In the Main method in the above example, we have created an instance of List<Employee> which is actually not a good practice. Reasons,
“List<Employee> employees = new List<Employee>();” this thing will create an instance of the list that’s not needed because if you see in the next line its return another instance and assign its reference to the variable.
Here are some tips to receive a good output from your code:
- Use For instead of Foreach. Foreach is also great but we need to figure it out based on requirements that what we actually need. For always work faster then Foreach.
- Use Switch instead of long If Else conditions. If else is good in case you need to just test 3 to 4 conditions. In case you need to test 10 conditions then always use Switch.
- Try to use Struct instead of Class in some cases based on requirements if possible then always use Struct instead of Class. As Struct is Stack type variable it works better.
- Try to avoid unnecessary collection enumerations and allocation.
- Use List instead of Dictionary.
- Do not call the async method from the sync method.
- Avoid string manipulation in a loop. Use Span in place of string.Substring() and string.concat in place of string.format
- Make use of Ref. and Out in C#, it avoids an unnecessary memory allocation.