Generics in C#

Starting with version 1.0, C# has added support for *generics*.

As an example of a generic method, `SlicesIndex` takes an `IEnumerable<T>` of any type `T` that implements `IEquatable<T>` and an element of that type, and returns the index of the first occurrence of `v` in `s`, or -1 if not present. The `IEquatable<T>` constraint means that we can compare values of this type with the `Equals` method.

```csharp
public static int SlicesIndex<T>(IEnumerable<T> s, T v) where T : IEquatable<T>
{
    int index = 0;
    foreach (var item in s)
    {
        if (item.Equals(v))
        {
            return index;
        }
        index++;
    }
    return -1;
}

As an example of a generic type, List<T> is a singly-linked list with values of any type.

public class List<T>
{
    private Element<T> head;
    private Element<T> tail;

    private class Element<T>
    {
        public Element<T> Next { get; set; }
        public T Value { get; set; }
    }

    public void Push(T v)
    {
        if (tail == null)
        {
            head = new Element<T> { Value = v };
            tail = head;
        }
        else
        {
            tail.Next = new Element<T> { Value = v };
            tail = tail.Next;
        }
    }

    public IEnumerable<T> AllElements()
    {
        var current = head;
        while (current != null)
        {
            yield return current.Value;
            current = current.Next;
        }
    }
}

Here’s how we can use these generic types and methods:

class Program
{
    static void Main(string[] args)
    {
        var s = new List<string> { "foo", "bar", "zoo" };

        Console.WriteLine($"index of zoo: {SlicesIndex(s, "zoo")}");

        var lst = new List<int>();
        lst.Push(10);
        lst.Push(13);
        lst.Push(23);
        Console.WriteLine($"list: [{string.Join(", ", lst.AllElements())}]");
    }
}

When invoking generic methods, we can often rely on type inference. Note that we don’t have to specify the type for T when calling SlicesIndex - the compiler infers it automatically.

The output of this program would be:

index of zoo: 2
list: [10, 13, 23]

This example demonstrates how generics in C# allow us to write flexible, reusable code that works with different types while maintaining type safety.