泛型(五)

風靈使發表於2019-01-12

泛型委託(C# 程式設計指南)

委託可以定義它自己的型別引數。 引用泛型委託的程式碼可以指定型別引數以建立封閉式構造型別,就像例項化泛型類或呼叫泛型方法一樣,如以下示例中所示:

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

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

C# 2.0 版具有一種稱為方法組轉換的新功能,適用於具體委託型別和泛型委託型別,使你能夠使用此簡化語法編寫上一行:

Del<int> m2 = Notify;

在泛型類中定義的委託可以用類方法使用的相同方式來使用泛型類型別引數。

class Stack<T>
{
    T[] items;
    int index;

    public delegate void StackDelegate(T[] items);
}

引用委託的程式碼必須指定包含類的型別引數,如下所示:

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

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

根據典型設計模式定義事件時,泛型委託特別有用,因為發件人引數可以為強型別,無需在它和 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)
    {
        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;
}


泛型和特性(C# 程式設計指南)

屬性可按與非泛型型別相同的方式應用到泛型型別。 有關應用特性的詳細資訊,請參閱屬性。

僅允許自定義屬性引用開放式泛型型別(即未向其提供任何型別引數的泛型型別)和封閉式構造泛型型別(即向所有型別引數提供引數的泛型型別)。

以下示例使用此自定義屬性:

class CustomAttribute : System.Attribute
{
    public System.Object info;
}

屬性可引用開放式泛型型別:

public class GenericClass1<T> { }

[CustomAttribute(info = typeof(GenericClass1<>))]
class ClassA { }

通過使用適當數量的逗號指定多個型別引數。 在此示例中,GenericClass2 具有兩個型別引數:

public class GenericClass2<T, U> { }

[CustomAttribute(info = typeof(GenericClass2<,>))]
class ClassB { }

屬性可引用封閉式構造泛型型別:

public class GenericClass3<T, U, V> { }

[CustomAttribute(info = typeof(GenericClass3<int, double, string>))]
class ClassC { }

引用泛型型別引數的屬性會導致編譯時錯誤:

//[CustomAttribute(info = typeof(GenericClass3<int, T, string>))]  //Error
class ClassD<T> { }

不能從Attribute繼承泛型型別:

//public class CustomAtt<T> : System.Attribute {}  //Error

若要在執行時獲取有關泛型型別或型別引數的資訊,可使用 System.Reflection 方法。 有關詳細資訊,請參閱泛型和反射

相關文章