A policy is more general than a strategy. It is a generic set of rules with room for interpretation. When the strategy is itself generic, then it is a policy; it can be applied to several types.

Take, for example, a policy for prioritizing work. It can be done last-in-first-out as a stack, or first-in-first-out as a queue. The exact form of the work item is not important to the method used. It's just a general policy for ordering work.

Public Interface IOrderingPolicy(Of T)

    Sub PutItem(ByVal value As T)
    Function GetItem() As T

End Interface

Public Class WorkList(Of T As IWorkItem, _
        OrderingPolicy As _
            {IOrderingPolicy(Of T), New})

    Private _orderingPolicy As _
        New OrderingPolicy()

    Public Sub AddWork(ByVal item As T)
        _orderingPolicy.PutItem(item)
    End Sub

    Public Sub Work()
        Dim item As T
        item = _orderingPolicy.GetItem
        item.DoWork()
    End Sub

End Class
public interface IOrderingPolicy<T>
{
    void PutItem(T value);
    T GetItem();
}

public class WorkList<T, OrderingPolicy>
    where OrderingPolicy :
        IOrderingPolicy<T>, new()
    where T : IWorkItem
{
    private OrderingPolicy _orderingPolicy =
        new OrderingPolicy();

    public void AddWork(T item)
    {
        _orderingPolicy.PutItem(item);
    }

    public void Work()
    {
        T item = _orderingPolicy.GetItem();
        item.DoWork();
    }
}

The consumer of a policy has two type placeholders: one for the policy and another for the item type that it acts upon. The placeholder for the item type is used in the constraint for the policy type. When the generic type is expanded, the item type needs to be expressed twice. Since generics lack the power of C++ "template template parameters", this redundancy cannot be eliminated.

Public Class FIFO(Of T)
    Implements IOrderingPolicy(Of T)

    Private _queue As New Queue(Of T)

    Public Sub PutItem(ByVal item As T) _
        Implements IOrderingPolicy (Of T) _
            .PutItem
        _queue.Enqueue(item)
    End Sub

    Public Function GetItem() As T _
        Implements IOrderingPolicy(Of T) _
            .GetItem
        Return _queue.Dequeue()
    End Function

End Class

Dim workList As New _
    WorkList(Of WorkItem, FIFO(Of WorkItem))
workList.AddWork(New WorkItem)
workList.Work()
public class FIFO<T> : IOrderingPolicy<T>
{
    private Queue<T> _queue = new Queue<T>();

    public void PutItem(T value)
    {
        _queue.Enqueue(value);
    }

    public T GetItem()
    {
        return _queue.Dequeue();
    }
}





WorkList<WorkItem, FIFO<WorkItem>> workList =
    new WorkList<WorkItem, FIFO<WorkItem>>();
workList.AddWork(new WorkItem());
workList.Work();