Obecné typy v .NET

Obecné typy umožňují přizpůsobit metodu, třídu, strukturu nebo rozhraní na přesný datový typ, na kterém funguje. Například namísto použití Hashtable třídy, která umožňuje klíčům a hodnotám být libovolného typu, můžete použít Dictionary<TKey,TValue> obecnou třídu a zadat typy povolené pro klíč a hodnotu. Z výhod obecných typů se zvyšuje použitelnost kódu a bezpečnost typů.

Definování a použití generický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é jsou uloženy nebo použity. Třída obecné kolekce může používat parametr typu jako zástupný symbol pro typ objektů, které úložiště ukládá; parametry typu se zobrazí jako typy polí a typy parametrů jejich metod. Obecná metoda může použít svůj parametr typu jako typ své návratové hodnoty nebo jako typ jednoho z jeho formálních parametrů. Následující kód ilustruje 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é mají být nahrazeny parametry typu. Tím se vytvoří nová Obecná třída označovaná jako konstruovaná obecná třída s vybranými typy, které jsou nahrazeny všude, kde se objeví parametry typu. Výsledkem je typově bezpečná třída, která je upravena podle vašeho výběru typů, jak ukazuje 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 generických typů

Pro diskuzi o obecných typech v rozhraní .NET se používají následující výrazy:

  • 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žít. System.Collections.Generic.Dictionary<TKey,TValue>Třída může například obsahovat dva typy: klíče a hodnoty. Vzhledem k tomu, že definice obecného typu je pouze šablona, nelze vytvořit instance třídy, struktury nebo rozhraní, které je definicí obecného typu.

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

  • Konstruovaný obecný typ, neboli konstruovaný typ, je výsledkem určení typů pro parametry obecného typu definice obecného typu.

  • Argument obecného typu je libovolný typ, který je nahrazen parametrem obecného typu.

  • Obecný typ běžné podmínky zahrnuje konstruované typy i definice obecného typu.

  • Kovariance a kontravariance parametrů obecného typu umožňuje použít konstruované obecné typy, jejichž argumenty typu jsou více odvozené (kovariance) nebo méně odvozené (kontravariance) než cílový konstruovaný typ. Kovariance a kontravariance jsou souhrnně označovány jako Variance. Další informace najdete v tématu kovariance a kontravariance.

  • Omezení jsou omezení pro parametry obecného typu. Například můžete omezit parametr typu na typy, které implementují System.Collections.Generic.IComparer<T> Obecné rozhraní, aby bylo zajištěno, že lze seřadit instance daného typu. Můžete také omezit parametry typu na typy, které mají konkrétní základní třídu, která má konstruktor bez parametrů, nebo, které jsou odkazové typy nebo hodnoty. Uživatelé obecného typu nemohou dosadit argumenty typu, které nesplňují omezení.

  • Obecná definice metody je metoda se dvěma seznamy parametrů: seznam parametrů obecného typu a seznam formálních parametrů. Parametry typu se mohou zobrazit 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 vyskytovat na obecných nebo neobecných typech. Je důležité si uvědomit, že metoda není obecná, protože patří do obecného typu, nebo i když má formální parametry, jejichž typy jsou obecné parametry nadřazeného typu. Metoda je obecná pouze v případě, že má svůj vlastní seznam parametrů typu. V následujícím kódu je pouze metoda G Obecná.

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á mnoho výhod:

  • Bezpečnost typů. Obecné typy posunou zatížení typu zabezpečení od vás do kompilátoru. Není nutné psát kód pro testování správného datového typu, protože je vynutila v době kompilace. Je potřeba snížit typ přetypování a možnost chyb za běhu.

  • Méně kód a kód je snazší znovu použít. Není nutné dědit ze základního typu a přepsat členy. Například LinkedList<T> je 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ě poskytují lepší pro ukládání a manipulaci s typy hodnot, protože není nutné pole hodnot.

  • Obecné Delegáti umožňují typově bezpečná zpětná volání bez nutnosti vytvářet více tříd delegátů. Například Predicate<T> obecný delegát umožňuje vytvořit metodu, která implementuje vlastní kritéria hledání pro konkrétní typ a použít metodu s metodami Array typu Find , jako jsou, FindLast a FindAll .

  • Obecné zjednodušují dynamicky generovaný kód. Použijete-li obecné typy s dynamicky generovaným kódem, nemusíte generovat typ. Tím se zvyšuje počet scénářů, ve kterých lze použít zjednodušené dynamické metody namísto generování celých sestavení. Další informace naleznete v tématu How to: Define and Execute Dynamic Methods and DynamicMethod .

Níže jsou uvedena některá omezení obecných typů:

  • Obecné typy lze odvodit z většiny základních tříd, například MarshalByRefObject (a omezení lze použít pro vyžadování, aby parametry obecného typu byly odvozeny ze základních tříd, jako MarshalByRefObject ). Rozhraní .NET však nepodporuje kontextově vázaných obecných typů. Obecný typ lze odvodit z ContextBoundObject , ale při pokusu o vytvoření instance tohoto typu dojde k TypeLoadException .

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

  • Jednoduché dynamické metody nemůžou být obecné.

  • v Visual Basic, C# a C++ nelze vytvořit instanci vnořeného typu, který je uzavřen v obecném typu, pokud typy nejsou přiřazeny k parametrům typu všech nadřazených typů. Dalším způsobem, jak to vyjádřit, je vnořený typ, který je definován pomocí těchto jazyků, obsahuje parametry typu všech nadřazených typů. To umožňuje, aby parametry typu nadřazených typů byly použity v definicích členů vnořeného typu. Další informace naleznete v části "vnořené typy" v tématu MakeGenericType .

    Poznámka

    Vnořený typ, který je definován vygenerováním kódu v dynamickém sestavení nebo pomocí Ilasm.exe (IL Assembler) , není vyžadován pro zahrnutí parametrů typu jejich nadřazených typů; Pokud je však neobsahuje, parametry typu nejsou v oboru vnořené třídy.

    Další informace naleznete v části "vnořené typy" v tématu MakeGenericType .

Knihovna tříd a podpora jazyků

Rozhraní .NET poskytuje řadu obecných tříd kolekcí 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ů společně s obecnými typy delegátů pro obslužné rutiny událostí, převody a predikáty vyhledávání.

Do oboru názvů se přidala podpora pro obecné System.Reflection typy pro zkoumání obecných typů a obecných metod, pro System.Reflection.Emit generování dynamických sestavení, která obsahují obecné typy a metody, a pro System.CodeDom generování zdrojových grafů, které obsahují obecné typy.

Modul CLR (Common Language Runtime) poskytuje nové operační kódy a předpony pro podporu obecných typů v jazyce MSIL (Microsoft Intermediate Language), včetně,,, Stelem Ldelem Unbox_Any Constrained a Readonly .

Visual C++, C# a Visual Basic poskytují úplnou podporu pro definování a používání obecných typů. další informace o podpoře jazyků naleznete v tématu obecné typy v Visual Basic, úvod do obecnýchhodnot a přehled obecných typů v Visual C++.

Vnořené typy a obecné typy

Typ, který je vnořen v obecném typu, může záviset na parametrech typu nadřazeného obecného typu. Modul CLR (Common Language Runtime) považuje vnořené typy za obecné, a to i v případě, že nemají vlastní parametry obecného typu. Při vytváření instance vnořeného typu je nutné zadat argumenty typu pro všechny nadřazené obecné typy.

Nadpis Popis
Obecné kolekce v .NET Popisuje třídy obecných kolekcí a jiné obecné typy v rozhraní .NET.
Obecné delegáty pro manipulaci s poli a seznamy Popisuje Obecné delegáty pro převody, predikáty hledání a akce, které mají být provedeny na prvcích pole nebo kolekce.
Obecná rozhraní Popisuje Obecná rozhraní, která poskytují společné funkce napříč rodinami obecných typů.
Kovariance a kontravariance Popisuje kovariance a kontravariance v parametrech obecného typu.
Běžně používané typy kolekcí Obsahuje souhrnné informace o vlastnostech a scénářích použití typů kolekcí v rozhraní .NET, včetně obecných typů.
Kdy použít obecné kolekce Popisuje obecná pravidla pro určení, kdy použít typy obecných kolekcí.
Postupy: Definování obecného typu pomocí generování reflexe Vysvětluje, jak generovat dynamická sestavení, která zahrnují obecné typy a metody.
Obecné typy v Visual Basic popisuje funkci generics 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 o definování a použití obecných typů pro uživatele v jazyce C#.
Přehled obecných typů v Visual C++ Popisuje funkci obecných typů 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