Syntax
class ClassName<T> {\n // T can be used as a type\n}Examples
Basic Generic Class
A class that works with any type, specified when it is used.
public class Box<T>
{
private T _content = default!;
public void Set(T content) => _content = content;
public T Get() => _content;
}
Box<string> stringBox = new Box<string>();
stringBox.Set("Hello");
Console.WriteLine(stringBox.Get()); // Hello
Box<int> intBox = new Box<int>();
intBox.Set(42);
Console.WriteLine(intBox.Get()); // 42Generic Methods
A single method can be generic even inside a non-generic class.
public class Utils
{
public static void PrintArray<T>(T[] array)
{
foreach (T item in array)
{
Console.WriteLine(item);
}
}
}
int[] numbers = { 1, 2, 3 };
string[] words = { "a", "b", "c" };
Utils.PrintArray(numbers);
Utils.PrintArray(words);Multiple Type Parameters
A generic class or interface can have more than one type parameter, like Dictionary<TKey, TValue>.
public class Pair<TKey, TValue>
{
public TKey Key { get; }
public TValue Value { get; }
public Pair(TKey key, TValue value)
{
Key = key;
Value = value;
}
public override string ToString() => $"{Key} -> {Value}";
}
Pair<string, int> pair = new Pair<string, int>("age", 21);
Console.WriteLine(pair); // age -> 21Generic Constraints
Restricting a generic type with 'where', so it must satisfy certain requirements.
public class NumberBox<T> where T : struct, IComparable<T>
{
public T Value { get; }
public NumberBox(T value) => Value = value;
public bool IsGreaterThan(T other) => Value.CompareTo(other) > 0;
}
NumberBox<int> box = new NumberBox<int>(10);
Console.WriteLine(box.IsGreaterThan(5)); // trueBest practices
- Use generics whenever a class or method's logic is the same regardless of type, to avoid duplicating code for each specific type
- Follow C# naming conventions for type parameters: T for a single general type, TKey/TValue for a key-value pair, TResult for a return type
- Use generic constraints (where T : ...) when your generic code needs to call methods specific to a certain family of types
- Prefer generics over using object and manual casting - generics catch type errors at compile time instead of causing an InvalidCastException at runtime
At a glance
- Purpose
- Applications on the .NET platform
- File extension
- .cs
- Runs in
- .NET runtime
- Usually used with
- .NET SDK and libraries
Specifications & further reading
Related C# documentation
A class is a blueprint for creating objects, bundling related data (fields/properties) and behavior (methods) together. C# is a fully object-oriented language - every application has at least one class, typically with a Main method as its entry point. An object is a specific instance of a class, created with the new keyword, with its own independent copy of the class's instance data.Constructors
A constructor is a special method that runs automatically when an object is created with new, used to initialize the object's state. A constructor shares its name with the class and has no return type. C# supports constructor overloading (multiple constructors with different parameter lists) and constructor chaining with this(...), where one constructor calls another in the same class to avoid duplicating initialization logic.Properties (get/set)
Properties are C#'s idiomatic way to expose class data through accessor-like syntax while still allowing controlled access via get and set. Unlike a plain public field, a property can validate a value before it's set, compute a value on the fly, or restrict access to read-only. Auto-implemented properties (using { get; set; } with no body) provide a concise shorthand when no custom logic is needed.Access Modifiers
Access modifiers control the visibility of classes, fields, methods, and properties from other parts of a program. C# provides public (accessible from anywhere), private (accessible only within the declaring class - the default for class members), protected (accessible within the class and its subclasses), internal (accessible only within the same assembly/project), and combinations like protected internal and private protected.