Understanding Generics in .NET: Part 1

Understanding Generics in .NET: Part 1

In this article, i will illustrate the benefits of using generics in C# . Consider a scenario where we want to create a repository class to manage entities in an application. We will compare the implementation using the object type with the implementation using generics.

Without Generics (Using object type)

First, let's see how it would look if we use the object type:

public class ObjectRepository
{
    private List<object> _items = new List<object>();

    public void AddItem(object item)
    {
        _items.Add(item);
    }

    public object GetItem(int index)
    {
        return _items[index];
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
        ObjectRepository repository = new ObjectRepository();
        repository.AddItem(new Product { Id = 1, Name = "Laptop" });
        repository.AddItem(new Customer { Id = 1, Name = "Vu" });

        Product product = (Product)repository.GetItem(0);
        Customer customer = (Customer)repository.GetItem(1);

        Console.WriteLine($"Product: {product.Name}");
        Console.WriteLine($"Customer: {customer.Name}");
    }
}        


Issues with the above approach:

  1. Type Safety: The compiler does not check the types of objects being added or retrieved. This can lead to runtime errors if incorrect type casting occurs.
  2. Performance: Value types added to the list will be boxed, and unboxing will be required when retrieving them, which is inefficient.
  3. Code Reusability: Although the code is reusable, it lacks type specificity, which can be problematic.
  4. Type Casting: Explicit type casting is required when retrieving items, making the code less readable and more error-prone.

With Generics

Now, let's see how we can improve this using generics:

public class Repository<T>
{
    private List<T> _items = new List<T>();

    public void AddItem(T item)
    {
        _items.Add(item);
    }

    public T GetItem(int index)
    {
        return _items[index];
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
        Repository<Product> productRepository = new Repository<Product>();
        productRepository.AddItem(new Product { Id = 1, Name = "Laptop" });

        Repository<Customer> customerRepository = new Repository<Customer>();
        customerRepository.AddItem(new Customer { Id = 1, Name = "Vu" });

        Product product = productRepository.GetItem(0);
        Customer customer = customerRepository.GetItem(0);

        Console.WriteLine($"Product: {product.Name}");
        Console.WriteLine($"Customer: {customer.Name}");
    }
}        

Advantages of the Generic Approach:

  1. Type Safety: The compiler ensures that only objects of type T are added to the repository. This eliminates the risk of runtime type errors.
  2. Performance: There's no need for boxing or unboxing since the type is known at compile time, leading to more efficient operations.
  3. Code Reusability: The Repository<T> class can be reused for any type, reducing code duplication while still maintaining type specificity.
  4. Elimination of Type Casting: No explicit type casting is required when retrieving items, making the code cleaner and more readable.

By using generics, we achieve a more robust, efficient, and maintainable solution. This is especially useful when applied in the Generic Repository Pattern to access and manipulate data in database tables.

To view or add a comment, sign in

More articles by Vu Truong Huu

Insights from the community

Others also viewed

Explore topics