Sdílet prostřednictvím


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ý působí. Například místo použití Hashtable třídy, která umožňuje klíče a hodnoty jakéhokoli 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ů.

Definice a použití 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 zobrazují jako typy polí a typy parametrů jeho metod. Obecná metoda může použít parametr typu jako typ jeho návratové hodnoty nebo jako typ jednoho z jeho formálních parametrů.

Následující kód znázorňuje jednoduchou definici obecné třídy.

public class SimpleGenericClass<T>
{
    public T Field;
}
Public Class SimpleGenericClass(Of T)
    Public Field As T

End Class

Když vytvoříte instanci 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 generovaná obecná třída s vybranými typy nahrazenými všude, 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.

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

Terminologie

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. Protož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 obecném typu nebo definici metody. Obecný System.Collections.Generic.Dictionary<TKey,TValue> typ má dva parametry typu, TKey a TValue, které představují typy jeho klíčů a hodnot.

  • Vytvořený obecný typ nebo vytvořený 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ý termín obecný typ zahrnuje konstruované typy i definice obecného typu.

  • Kovariance a kontravariance parametrů obecného typu umožňují použít 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 varianta. Další informace naleznete v tématu Kovariance a kontravariance.

  • Omezení jsou omezení u parametrů obecného 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é nesplňují omezení.

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

    T MyGenericMethod<T>(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
    
    Function MyGenericMethod(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 .

    class A
    {
        T G<T>(T arg)
        {
            T temp = arg;
            //...
            return temp;
        }
    }
    class MyGenericClass<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 MyGenericClass(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 přenášejí zodpovědnost za bezpečnost typů z vás na kompilátor. Není nutné psát kód pro testování správného datového typu, protože se vynucuje v době kompilace. Nutnost přetypování a možnost chyb za běhu se sníží.

  • Méně kódu a kód se snadněji znovu používá. 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 = 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.

  • Generické delegáty 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í vyhledávací kritéria pro určitý typ a použití vaší metody s metodami typu Array, jako je Find, FindLast a FindAll.

  • Obecné typy zjednodušují dynamicky generovaný kód. Pokud používáte obecné typy s dynamicky vygenerovaným kódem, nemusíte typ generovat. Tím se zvýší počet scénářů, ve kterých můžete místo generování celých sestavení použít odlehčené 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, například MarshalByRefObject (a omezení lze použít k vyžadování, aby parametry obecného typu odvozeny od základních tříd jako MarshalByRefObject). .NET však nepodporuje obecné typy vázané na kontext. Obecný typ může být odvozen z ContextBoundObject, ale pokud se pokusíte vytvořit instanci tohoto typu, způsobí to TypeLoadException.

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

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

  • V jazyce Visual Basic, C# a C++ nelze vytvořit instanci vnořeného typu, pokud nebyly typy přiřazeny parametrům typu u všech obklopujících typů. Dalším způsobem, jak to říct, je, že v reflexi vnořený typ definovaný pomocí těchto jazyků zahrnuje parametry typu všech typů, které ho obklopují. To umožňuje použít parametry typu ohraničující typy v definicích členů vnořeného typu. Další informace naleznete v tématu "Vnořené typy" v MakeGenericType.

    Poznámka:

    Vnořený typ, který je definován generováním kódu v dynamickém sestavení nebo pomocí Ilasm.exe (IL Assembler), nemusí zahrnovat parametry typu jeho obklopujících typů; pokud je však nezahrne, tyto parametry nejsou dostupné v definici vnořené třídy.

    Další informace naleznete v tématu "Vnořené typy" v MakeGenericType.

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í.

Obor System.Numerics názvů poskytuje obecná rozhraní pro matematické funkce (dostupné v .NET 7 a novějších verzích). Další informace najdete v tématu Obecná matematika.

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 pro System.CodeDom generování zdrojových grafů, které obsahují obecné typy.

Modul CLR (Common Language Runtime) poskytuje nové opkódy a předpony pro podporu obecných typů v běžném přechodném jazyce (CIL), 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 jazyka naleznete v tématu Obecné typy v jazyce Visual Basic, Úvod do obecných typů a Přehled obecných typů v jazyce Visual C++.

Vnořené typy a generika

Typ, který je vnořený do generického typu, může záviset na typech parametrů obklopujícího generického typu. Modul CLR (Common Language Runtime) považuje vnořené typy za obecné, i když nemají vlastní parametry obecného typu. Při vytváření instance vnořeného typu je nutné zadat argumenty typu pro všechny uzavřené obecné typy.

Titulek 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, vyhledávací predikáty a akce prováděné u prvků pole nebo kolekce.
Obecná matematika Popisuje, jak můžete provádět matematické operace obecně.
Obecná rozhraní Popisuje obecná rozhraní, která poskytují společné funkce napříč rodinami obecných typů.
Kovariance a kontravariance Popisuje kovarianci a kontravarianci v parametrech obecného typu.
Běžně používané typy kolekcí Poskytuje souhrnné informace o charakteristikách 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í.
Jak na: Definování obecného typu pomocí Reflection Emit Vysvětluje, jak generovat dynamická sestavení, která obsahují obecné typy a metody.
Obecné typy v jazyce Visual Basic Popisuje obecnou funkci pro uživatele jazyka Visual Basic, včetně témat s postupy pro použití a definování obecných typů.
Úvod do generik 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.

Odkazy