[C#] Generics and Extension Methods

Date:     Updated:

Categories:

Tags:

📋 This is my note-taking from what I learned in the course!


Generics and Extension Methods

Objectives

  • Create generic methods.
  • Overload generic methods with non-generic methods or other generic methods.
  • Understand the kinds of constraints that can be applied to a type parameter.
  • Apply multiple constraints to a type parameter.

Generics Overview

Generics introduce the concept of type parameters, allowing the creation of classes and methods that are independent of specific types. The specification of types can be deferred until the class or method is instantiated by client code. Generics provide type safety, performance, and productivity without compromising any of these aspects.

Generic Parameterization

Generics can be used with:

  • Types (Struct, Interface, Class, Delegate)
  • Methods

Struct Example

Structs are value types stored on the stack and do not support inheritance. Each simple type in C# has a corresponding struct in the System namespace, such as Boolean, Byte, Char, Decimal, Double, Int32, etc.

Simple-Type Structs

Simple types are aliases for their corresponding structs, and methods related to a simple type are located in the corresponding struct.

Boxing and Unboxing

Boxing converts a value type to an object type, allowing simple types to be manipulated as objects. Unboxing extracts the value type from the object.

Boxing Example

int i = 5; // create an int value
object object1 = (object)i; // explicitly box the int value
object object2 = i; // implicitly box the int value

Unboxing Example

int int1 = (int)object1; // explicitly unbox the int value

Generic Classes

Generic classes allow defining type parameters, enabling different types to be used during compile time. This allows for type safety and code reuse.

Example: Generic Class

public class GenericClass<T> {
    private T value;

    public GenericClass(T value) {
        this.value = value;
    }

    public T GetValue() {
        return value;
    }
}

Generic Methods

Generic methods specify a set of related methods with a single method declaration. They use type parameters as placeholders for actual types.

Example: Generic Method

public static T GenericMethod<T>(T input) {
    return input;
}

IComparable Interface

The IComparable<T> interface allows comparison of two objects of the same type using the CompareTo() method.

CompareTo Method

public int CompareTo(T other) {
    // Implementation
}

Type Constraints

Type constraints restrict the types that can be used with a generic method or class.

Types of Constraints

  • where T : struct - T must be a value type.
  • where T : class - T must be a reference type.
  • where T : IFoo - T must implement interface IFoo.
  • where T : new() - T must have a default constructor.
  • where T1 : T2 - T1 must derive from T2.

Example: Multiple Constraints

public class Example<T> where T : class, IFoo, new() {
    // Implementation
}

Default Values for Generic Types

Default values are used for generic types that can be instantiated as value types or reference types.

T defaultValue = default(T);

Extension Methods

Extension methods extend the functionality of existing classes without modifying their source code. They are static methods defined in static classes and use the this modifier on the first parameter to specify the type being extended.

Example: Extension Method

public static class StringExtensions {
    public static string ToUpperFirstLetter(this string str) {
        if (string.IsNullOrEmpty(str)) return str;
        return char.ToUpper(str[0]) + str.Substring(1);
    }
}

// Usage
string example = "hello";
string result = example.ToUpperFirstLetter(); // "Hello"

Reference: Extension Methods




Back to Top

See other articles in Category CS

Leave a comment