Generics
Write type-parameterized methods and classes with constraints.
Code
using System;
using System.Collections.Generic;
// Generic method with constraint
T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;
// Generic class
public class Stack<T>
{
private readonly List<T> _items = new();
public int Count => _items.Count;
public void Push(T item) => _items.Add(item);
public T Pop()
{
if (_items.Count == 0) throw new InvalidOperationException("empty");
var top = _items[^1];
_items.RemoveAt(_items.Count - 1);
return top;
}
}
// Generic dictionary cache
public class Cache<TKey, TValue> where TKey : notnull
{
private readonly Dictionary<TKey, TValue> _data = new();
public TValue GetOrAdd(TKey key, Func<TKey, TValue> factory)
{
if (!_data.TryGetValue(key, out var value))
_data[key] = value = factory(key);
return value;
}
}
Console.WriteLine(Max(3, 7));
Console.WriteLine(Max("apple", "pear"));
var s = new Stack<int>();
s.Push(1); s.Push(2);
Console.WriteLine(s.Pop());
var cache = new Cache<string, int>();
Console.WriteLine(cache.GetOrAdd("a", k => k.Length));Explanation
Generics let you write one type- or method-parameterized definition that works for any type while preserving compile-time type safety. Constraints like IComparable<T> or notnull tell the compiler what members the type argument must have. The JIT creates a specialized implementation per value type, avoiding boxing overhead.
More C# Snippets
LINQ Query
Filter, project, sort, group, and aggregate sequences with LINQ.
Async and Await
Run I/O concurrently with async methods, await, and Task.WhenAll.
Properties
Encapsulate state with auto, computed, validated, and init-only properties.
Delegates and Events
Define delegate types and publish events with safe subscription.
Reflection
Inspect type metadata and invoke members at runtime via System.Reflection.
Collections
Use List, Dictionary, HashSet, Queue, Stack, and read-only views.