Mastering Generics and Custom Interfaces in C# on Day 29
Written on
Introduction to Generics and Interfaces
In the realm of software development, it's common for developers to inadvertently introduce unnecessary boxing, which can negatively impact application performance. On Day 29 of our 30-Day .NET Challenge, we will delve into the concept of boxing and how to leverage generics and custom interfaces to create more efficient code.
Learning Goals
- Understand the concept of boxing
- Recognize the inefficiencies of non-generic interface approaches
- Learn a better method utilizing generics
Prerequisites for Developers
- A fundamental grasp of the C# programming language
What is Boxing?
Boxing refers to the transformation of a value type into an object type, effectively allocating memory on the heap instead of the stack. This results in performance overhead due to increased memory consumption and the necessity of garbage collection.
Inefficiencies of Non-Generic Interfaces
In the following example, each assignment to the Value property requires boxing, leading to performance bottlenecks:
public interface INumber
{
object Value { get; set; }
}
public class Number : INumber
{
public object Value { get; set; }
}
A Recommended Approach Using Generics
Below is a revised version of the previous code snippet employing generics, which ensures type safety without the drawbacks of boxing:
public interface INumber<T>
{
T Value { get; set; }
}
public class Number<T> : INumber<T>
{
public T Value { get; set; }
public Number(T value)
{
Value = value;}
}
How to Utilize Generics in Practice
You can create instances with different types, like so:
var intNumber = new Number<int> { Value = 123 };
var floatNumber = new Number<float> { Value = 123.45f };
Complete Code Example
To illustrate the use of generics and custom interfaces, create another class named GenericCustomInterfaces and add the following code snippet:
public static class GenericCustomInterfaces
{
static List<Number<int>> intNumbers = new List<Number<int>>();
static List<Number<double>> doubleNumbers = new List<Number<double>>();
public static void Example()
{
// Populate the list with integers
for (int i = 0; i < 10; i++)
{
intNumbers.Add(new Number<int>(i));}
// Populate the list with doubles
for (double d = 0.5; d < 10.0; d += 1.0)
{
doubleNumbers.Add(new Number<double>(d));}
// Process and display integer numbers
Console.WriteLine("Integer Numbers:");
foreach (var num in intNumbers)
{
Console.WriteLine(num.Value);}
// Process and display double numbers
Console.WriteLine("nDouble Numbers:");
foreach (var num in doubleNumbers)
{
Console.WriteLine(num.Value);}
}
}
Implement the interface and its class as follows:
public interface INumber<T>
{
T Value { get; set; }
}
public class Number<T> : INumber<T>
{
public T Value { get; set; }
public Number(T value)
{
Value = value;}
}
Execute from the main method as follows:
#region Day 29: Generics & Custom Interfaces
static string ExecuteDay29()
{
GenericCustomInterfaces.Example();
return "Executed Day 29 successfully..!!";
}
#endregion
Console Output
The output will display:
Integer Numbers:
0
1
2
3
4
5
6
7
8
9
Double Numbers:
0.5
1.5
2.5
3.5
4.5
5.5
6.5
7.5
8.5
9.5
Complete Code on GitHub
Explore the full code on our GitHub repository for further insights into C# programming.
In this video, you'll learn how to apply structs effectively in real-world scenarios, enhancing your understanding of C# concepts.
Join us for Day 23 of the coding challenge where we build a Tic Tac Toe game from scratch, including a review of the process and coding techniques.