C# Interview Questions

36 Questions
C# Programming

C# Programming

Web DevelopmentFrontendBackendGame Dev

Question 27

What are generics in C#?

Answer:

Generics in C# allow you to define classes, methods, and data structures with a placeholder for the type of data they store or use. This provides type safety and performance benefits without sacrificing flexibility and code reusability. Generics were introduced in C# 2.0 and are part of the System.Collections.Generic namespace.

Key Features of Generics

  1. Type Safety:

    • Generics provide compile-time type checking, which helps catch errors early and eliminates the need for type casting.
  2. Performance:

    • Generics avoid the overhead associated with boxing and unboxing when using value types, leading to improved performance.
  3. Code Reusability:

    • Generics allow you to create reusable code components that work with any data type, reducing code duplication.

Generic Classes

A generic class uses type parameters to define the types it can work with. The type parameter is specified in angle brackets <T>.

Example:

public class GenericList<T>
{
    private T[] items;
    private int count;

    public GenericList(int capacity)
    {
        items = new T[capacity];
        count = 0;
    }

    public void Add(T item)
    {
        if (count < items.Length)
        {
            items[count++] = item;
        }
    }

    public T Get(int index)
    {
        if (index >= 0 && index < count)
        {
            return items[index];
        }
        throw new ArgumentOutOfRangeException();
    }
}

// Usage
var intList = new GenericList<int>(10);
intList.Add(1);
intList.Add(2);
Console.WriteLine(intList.Get(0)); // Output: 1

var stringList = new GenericList<string>(10);
stringList.Add("Hello");
stringList.Add("World");
Console.WriteLine(stringList.Get(1)); // Output: World

Generic Methods

A generic method defines type parameters in the method signature.

Example:

public class Utilities
{
    public static void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }
}

// Usage
int x = 1, y = 2;
Utilities.Swap(ref x, ref y);
Console.WriteLine($"x: {x}, y: {y}"); // Output: x: 2, y: 1

string str1 = "Hello", str2 = "World";
Utilities.Swap(ref str1, ref str2);
Console.WriteLine($"str1: {str1}, str2: {str2}"); // Output: str1: World, str2: Hello

Generic Interfaces

A generic interface defines type parameters that can be implemented by classes.

Example:

public interface IRepository<T>
{
    void Add(T item);
    T Get(int id);
}

public class Repository<T> : IRepository<T>
{
    private List<T> items = new List<T>();

    public void Add(T item)
    {
        items.Add(item);
    }

    public T Get(int id)
    {
        if (id >= 0 && id < items.Count)
        {
            return items[id];
        }
        throw new ArgumentOutOfRangeException();
    }
}

// Usage
var intRepository = new Repository<int>();
intRepository.Add(1);
intRepository.Add(2);
Console.WriteLine(intRepository.Get(0)); // Output: 1

var stringRepository = new Repository<string>();
stringRepository.Add("Hello");
stringRepository.Add("World");
Console.WriteLine(stringRepository.Get(1)); // Output: World

Constraints on Generics

You can impose constraints on generic type parameters to restrict the types that can be used.

Example:

public class Utilities
{
    // T must be a reference type
    public static void PrintObject<T>(T obj) where T : class
    {
        if (obj != null)
        {
            Console.WriteLine(obj.ToString());
        }
    }

    // T must have a parameterless constructor
    public static T CreateInstance<T>() where T : new()
    {
        return new T();
    }
}

Common Constraints

  • where T : struct - T must be a value type.
  • where T : class - T must be a reference type.
  • where T : new() - T must have a parameterless constructor.
  • where T : SomeBaseClass - T must inherit from SomeBaseClass.
  • where T : SomeInterface - T must implement SomeInterface.

Advantages of Generics

  1. Type Safety:

    • Generics allow you to catch type-related errors at compile time, reducing runtime errors.
  2. Performance:

    • Generics eliminate the need for boxing and unboxing, which improves performance for value types.
  3. Code Reusability:

    • Generic classes, methods, and interfaces can be used with any data type, reducing code duplication and improving maintainability.
  4. Flexibility:

    • Generics provide the flexibility to define data structures and algorithms that can work with any type.

Summary

Generics in C# provide a powerful way to create type-safe, reusable, and efficient code components. By using generic classes, methods, and interfaces, you can write flexible code that works with any data type while benefiting from compile-time type checking and improved performance. Constraints on generics allow you to enforce specific type requirements, further enhancing the robustness of your code.

Recent job openings