Condividi tramite


Delegati generici (Guida per programmatori C#)

Un delegato può definire i propri parametri di tipo. Il codice che fa riferimento al delegato generico può specificare l'argomento di tipo per creare un tipo costruito chiuso, proprio come quando si crea un'istanza di una classe generica o si chiama un metodo generico, come illustrato nell'esempio seguente:

public delegate void Del<T>(T item);
public static void Notify(int i) { }

Del<int> m1 = new Del<int>(Notify);

C# versione 2.0 include una nuova funzionalità denominata conversione del gruppo di metodi, che si applica a tipi delegati concreti e generici e consente di scrivere la riga precedente con questa sintassi semplificata:

Del<int> m2 = Notify;

I delegati definiti all'interno di una classe generica possono usare i parametri di tipo di classe generici nello stesso modo in cui i metodi della classe eseguono.

class Stack<T>
{
    public delegate void StackDelegate(T[] items);
}

Il codice che fa riferimento al delegato deve specificare l'argomento di tipo della classe contenitore, come indicato di seguito:

private static void DoWork(float[] items) { }

public static void TestStack()
{
    Stack<float> s = new Stack<float>();
    Stack<float>.StackDelegate d = DoWork;
}

I delegati generici sono particolarmente utili per definire gli eventi in base al modello di progettazione tipico perché l'argomento mittente può essere fortemente tipizzato e non deve più essere convertito a e da Object.

delegate void StackEventHandler<T, U>(T sender, U eventArgs);

class Stack<T>
{
    public class StackEventArgs : System.EventArgs { }
    public event StackEventHandler<Stack<T>, StackEventArgs>? StackEvent;

    protected virtual void OnStackChanged(StackEventArgs a)
    {
        if (StackEvent is not null)
            StackEvent(this, a);
    }
}

class SampleClass
{
    public void HandleStackChange<T>(Stack<T> stack, Stack<T>.StackEventArgs args) { }
}

public static void Test()
{
    Stack<double> s = new Stack<double>();
    SampleClass o = new SampleClass();
    s.StackEvent += o.HandleStackChange;
}

Vedere anche