liveBook · Manning

Generic interface

As explained in Fabulous Adventures in Data Structures and Algorithms

A generic interface is an interface parameterized by one or more type parameters.

A generic interface is an interface parameterized by one or more type parameters. It lets one abstraction describe operations over many possible types. IEnumerable<T> applies this idea to sequences; a distribution can use the same shape to produce values of type T. section 12.3

The smallest distribution interface exposes Sample(), returning a randomly generated T. A discrete extension adds Support() and Weight(T), separating the values that can occur from their relative probabilities. section 12.4 section 12.4

Generic interfaces become useful when the varying type is part of the problem’s structure:

  • Model probability distributions independently of whether they produce integers, cards, songs, or other values. section 12.3
  • Extend a base contract, as IDiscreteDistribution<T> extends IDistribution<T> with discrete-distribution operations. section 12.4
  • Represent operations over a family of expression-node types, as IExprVisitor<T> does for visitor results. section 9.4.1

A typed distribution contract

IDistribution<T> requires only T Sample(). IDiscreteDistribution<T> adds IEnumerable<T> Support() and int Weight(T). DiscreteUniform implements IDiscreteDistribution<int>, wrapping Random while exposing a reusable distribution abstraction. section 12.4

A generic visitor result

IExprVisitor<T> declares Visit methods for each expression subtype. Expr.Accept<T>(IExprVisitor<T>) supplies the missing type information so compiler overload resolution and runtime dispatch select the correct Visit method. section 9.4.1

Listing 12.1 An interface and the discrete uniform distribution
public interface IDistribution<T>
{
    T Sample();
}

public interface IDiscreteDistribution<T> : IDistribution<T>
{
    IEnumerable<T> Support();
    int Weight(T t);
}

public sealed class DiscreteUniform : IDiscreteDistribution<int>
{
    private readonly Random rnd = new();
    private readonly int max;
    public static DiscreteUniform Distribution(int max)
    {
        if (max <= 0)
            throw new InvalidOperationException();
        return new(max);
    }
    private DiscreteUniform(int max) => this.max = max;
    public int Sample() => rnd.Next(max);
    public IEnumerable<int> Support() => Enumerable.Range(0, max);
    public int Weight(int t) => 0 <= t && t < max ? 1 : 0;
}

Inspect the complete C# interface declarations and their discrete uniform implementation. section 12.4

How Fabulous Adventures in Data Structures and Algorithms covers it

How deep it goes
Builds distribution and visitor interfaces with implementations, then traces overload resolution and dispatch; it stops short of broader interface design.
Examples
Uses Random-backed discrete uniform distributions and expression-tree visitors returning a generic result type.
What you can do after
Build it from scratch as a C# contract, extend it through inheritance, and diagnose visitor dispatch when static types hide subtype-specific methods.
How it connects
Connects generic interfaces to IEnumerable, probability distributions, visitor pattern, overload resolution, covariance, contravariance, and category theory.

Also explained in

Compare how 2 books explain generic interface →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Fabulous Adventures in Data Structures and Algorithms. The section links point to the parts of the book it draws on.