Obecné typy v .NET

Obecné typy umožňují přizpůsobit metodu, třídu, strukturu nebo rozhraní přesnému datovému typu, na který pracuje. Například místo použití Hashtable třídy, která umožňuje, aby klíče a hodnoty byly libovolného typu, můžete použít Dictionary<TKey,TValue> obecnou třídu a zadat typy povolené pro klíč a hodnotu. Mezi výhody obecných typů patří zvýšená použitelnost kódu a bezpečnost typů.

Definování a používání obecných typů

Obecné typy jsou třídy, struktury, rozhraní a metody, které mají zástupné symboly (parametry typu) pro jeden nebo více typů, které ukládají nebo používají. Obecná třída kolekce může použít parametr typu jako zástupný symbol pro typ objektů, které ukládá; parametry typu se zobrazí jako typy polí a typy parametrů jeho metod. Obecná metoda může jako typ návratové hodnoty nebo jako typ jednoho z jeho formálních parametrů použít parametr typu. Následující kód znázorňuje jednoduchou definici obecné třídy.

generic<typename T>
public ref class Generics
{
public:
    T Field;
};
public class Generic<T>
{
    public T Field;
}
Public Class Generic(Of T)
    Public Field As T

End Class

Při vytváření instance obecné třídy zadáte skutečné typy, které se mají nahradit parametry typu. Tím se vytvoří nová obecná třída označovaná jako generovaná obecná třída s vybranými typy nahrazenými všude tam, kde se zobrazí parametry typu. Výsledkem je typově bezpečná třída, která je přizpůsobená vašemu výběru typů, jak znázorňuje následující kód.

static void Main()
{
    Generics<String^>^ g = gcnew Generics<String^>();
    g->Field = "A string";
    //...
    Console::WriteLine("Generics.Field           = \"{0}\"", g->Field);
    Console::WriteLine("Generics.Field.GetType() = {0}", g->Field->GetType()->FullName);
}
public static void Main()
{
    Generic<string> g = new Generic<string>();
    g.Field = "A string";
    //...
    Console.WriteLine("Generic.Field           = \"{0}\"", g.Field);
    Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}
Public Shared Sub Main()
    Dim g As New Generic(Of String)
    g.Field = "A string"
    '...
    Console.WriteLine("Generic.Field           = ""{0}""", g.Field)
    Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub

Terminologie obecných typů

Následující termíny se používají k diskuzi obecných typů v .NET:

  • Definice obecného typu je deklarace třídy, struktury nebo rozhraní, která funguje jako šablona, se zástupnými symboly pro typy, které může obsahovat nebo používat. Třída může například System.Collections.Generic.Dictionary<TKey,TValue> obsahovat dva typy: klíče a hodnoty. Vzhledem k tomu, že definice obecného typu je pouze šablona, nemůžete vytvořit instance třídy, struktury nebo rozhraní, které je obecnou definicí typu.

  • Parametry obecného typu nebo parametry typu jsou zástupné symboly v obecné definici typu nebo metody. Obecný System.Collections.Generic.Dictionary<TKey,TValue> typ má dva parametry TKey typu, TValuekteré představují typy klíčů a hodnot.

  • Vytvořený obecný typ nebo vytvořený typ je výsledkem zadávání typů pro obecné parametry typu definice obecného typu.

  • Obecný argument typu je libovolný typ, který je nahrazen obecným parametrem typu.

  • Obecný termín obecný typ zahrnuje jak vytvořené typy, tak definice obecného typu.

  • Kovariance a kontravariance obecných parametrů typu umožňují používat vytvořené obecné typy, jejichž argumenty typu jsou odvozenější (kovariance) nebo méně odvozené (kontravariance) než cílový konstruovaný typ. Kovariance a kontravariance se souhrnně označují jako rozptyl. Další informace naleznete v tématu Kovariance a Kontravariance.

  • Omezení jsou omezení uložená na obecných parametrech typu. Můžete například omezit parametr typu na typy, které implementují System.Collections.Generic.IComparer<T> obecné rozhraní, aby se zajistilo, že instance typu lze uspořádat. Parametry typu můžete také omezit na typy, které mají konkrétní základní třídu, které mají konstruktor bez parametrů nebo které jsou referenčními typy nebo typy hodnot. Uživatelé obecného typu nemohou nahradit argumenty typu, které nevyhovují omezením.

  • Definice obecné metody je metoda se dvěma seznamy parametrů: seznam obecných parametrů typu a seznam formálních parametrů. Parametry typu se můžou objevit jako návratový typ nebo jako typy formálních parametrů, jak ukazuje následující kód.

generic<typename T>
T Generic(T arg)
{
    T temp = arg;
    //...
    return temp;
}
T Generic<T>(T arg)
{
    T temp = arg;
    //...
    return temp;
}
Function Generic(Of T)(ByVal arg As T) As T
    Dim temp As T = arg
    '...
    Return temp
End Function

Obecné metody se můžou objevit na obecných nebo negenerických typech. Je důležité si uvědomit, že metoda není obecná pouze proto, že patří do obecného typu, nebo dokonce proto, že má formální parametry, jejichž typy jsou obecné parametry ohraničujícího typu. Metoda je obecná pouze v případě, že má vlastní seznam parametrů typu. V následujícím kódu je obecná pouze metoda G .

ref class A
{
    generic<typename T>
    T G(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
};
generic<typename T>
ref class Generic
{
    T M(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
};
class A
{
    T G<T>(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}
class Generic<T>
{
    T M(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}
Class A
    Function G(Of T)(ByVal arg As T) As T
        Dim temp As T = arg
        '...
        Return temp
    End Function
End Class
Class Generic(Of T)
    Function M(ByVal arg As T) As T
        Dim temp As T = arg
        '...
        Return temp
    End Function
End Class

Výhody a nevýhody obecných typů

Použití obecných kolekcí a delegátů má řadu výhod:

  • Bezpečnost typů. Obecné typy přemístí zátěž zabezpečení typů od vás do kompilátoru. Není nutné psát kód pro testování správného datového typu, protože se vynucuje v době kompilace. Potřeba přetypování typů a možnost chyb za běhu se snižuje.

  • Méně kódu a kódu se snadněji používá. Není nutné dědit ze základního typu a přepsat členy. Například je LinkedList<T> připravený k okamžitému použití. Můžete například vytvořit propojený seznam řetězců s následující deklarací proměnné:

    LinkedList<String^>^ llist = gcnew LinkedList<String^>();
    
    LinkedList<string> llist = new LinkedList<string>();
    
    Dim llist As New LinkedList(Of String)()
    
  • Lepší výkon. Obecné typy kolekcí obecně fungují lépe pro ukládání a manipulaci s typy hodnot, protože není nutné zadávat typy hodnot.

  • Obecné delegáty umožňují zpětné volání bez nutnosti vytvářet více tříd delegátů. Obecný delegát vám například Predicate<T> umožňuje vytvořit metodu, která implementuje vlastní kritéria hledání pro určitý typ a použít metodu Array s metodami typu, jako Findje , FindLasta FindAll.

  • Obecné typy zjednodušují dynamicky vygenerovaný kód. Pokud používáte obecné typy s dynamicky vygenerovaným kódem, nemusíte generovat typ. Tím se zvýší počet scénářů, ve kterých můžete místo generování celých sestavení použít jednoduché dynamické metody. Další informace naleznete v tématu Postupy: Definování a spouštění dynamických metod a DynamicMethod.

Tady jsou některá omezení obecných typů:

  • Obecné typy mohou být odvozeny od většiny základních tříd, jako MarshalByRefObject jsou (a omezení lze použít k vyžadování, aby obecné parametry typu byly odvozeny ze základních tříd, jako je MarshalByRefObject). Rozhraní .NET však nepodporuje obecné typy vázané na kontext. Obecný typ může být odvozen od ContextBoundObject, ale pokus o vytvoření instance tohoto typu způsobí TypeLoadException.

  • Výčty nemohou mít obecné parametry typu. Výčet může být obecný pouze náhodně (například proto, že je vnořený do obecného typu, který je definován pomocí Visual Basic, C# nebo C++). Další informace najdete v tématu Výčty v systému běžných typů.

  • Jednoduché dynamické metody nemohou být obecné.

  • V Visual Basic, C# a C++ nelze vytvořit instanci vnořeného typu, který je uzavřen do obecného typu, pokud nebyly typy přiřazeny k parametrům typu všech uzavřených typů. Dalším způsobem, jak to říct, je to, že v reflexi je vnořený typ, který je definován pomocí těchto jazyků, zahrnuje parametry typu všech jeho uzavřených typů. To umožňuje použití parametrů typu uzavřených typů v definicích členů vnořeného typu. Další informace najdete v tématu "Vnořené typy" v MakeGenericTypesouboru .

    Poznámka

    Vnořený typ, který je definován generováním kódu v dynamickém sestavení nebo pomocí Ilasm.exe (IL Assembler), není nutné zahrnout parametry typu jeho uzavřených typů; Pokud je však neobsahuje, parametry typu nejsou v oboru v vnořené třídě.

    Další informace najdete v tématu "Vnořené typy" v MakeGenericTypesouboru .

Podpora knihovny tříd a jazyka

.NET poskytuje řadu obecných tříd kolekce v následujících oborech názvů:

Obecná rozhraní pro implementaci porovnání řazení a rovnosti jsou k dispozici v System oboru názvů spolu s obecnými typy delegátů pro obslužné rutiny událostí, převody a predikáty vyhledávání.

Podpora obecných typů byla přidána do System.Reflection oboru názvů pro zkoumání obecných typů a obecných metod, pro System.Reflection.Emit generování dynamických sestavení obsahujících obecné typy a metody a generování System.CodeDom zdrojových grafů, které obsahují obecné typy a metody.

Modul CLR (Common Language Runtime) poskytuje nové opcode a předpony pro podporu obecných typů v jazyce MSIL (Microsoft Intermediate Language), včetně Stelem, , Ldelem, , Unbox_AnyConstraineda Readonly.

Visual C++, C# a Visual Basic všechny poskytují úplnou podporu pro definování a používání obecných typů. Další informace o podpoře jazyka najdete v tématu Obecné typy v Visual Basic, Úvod do obecných typů a Přehled obecných typů v jazyce Visual C++.

Vnořené typy a obecné typy

Typ, který je vnořený do obecného typu, může záviset na parametrech typu uzavřeného obecného typu. Modul CLR (Common Language Runtime) považuje vnořené typy za obecné, i když nemají vlastní parametry obecného typu. Když vytvoříte instanci vnořeného typu, musíte zadat argumenty typu pro všechny uzavřené obecné typy.

Nadpis Popis
Obecné kolekce v .NET Popisuje obecné třídy kolekcí a další obecné typy v .NET.
Obecné delegáty pro manipulaci s poli a seznamy Popisuje obecné delegáty pro převody, predikáty vyhledávání a akce, které se mají provést u prvků pole nebo kolekce.
Obecná rozhraní Popisuje obecná rozhraní, která poskytují společné funkce napříč rodinami obecných typů.
Kovariance a kontravariance Popisuje kovarianci a kontravarianci v obecných parametrech typu.
Běžně používané typy kolekcí Poskytuje souhrnné informace o vlastnostech a scénářích použití typů kolekcí v .NET, včetně obecných typů.
Kdy použít obecné kolekce Popisuje obecná pravidla pro určení, kdy použít obecné typy kolekcí.
Postupy: Definování obecného typu pomocí generování reflexe Vysvětluje, jak generovat dynamická sestavení, která obsahují obecné typy a metody.
Obecné typy v Visual Basic Popisuje funkci obecných typů pro Visual Basic uživatele, včetně témat s postupy pro použití a definování obecných typů.
Úvod do obecných typů Poskytuje přehled definování a používání obecných typů pro uživatele jazyka C#.
Přehled obecných typů v jazyce Visual C++ Popisuje obecnou funkci pro uživatele jazyka C++, včetně rozdílů mezi obecnými typy a šablonami.

Reference

System.Collections.Generic

System.Collections.ObjectModel

System.Reflection.Emit.OpCodes