Typy ogólne w .NET

Typy ogólne umożliwiają dostosowanie metody, klasy, struktury lub interfejsu do dokładnego typu danych, na którym działa. Na przykład zamiast używać Hashtable klasy , która umożliwia używanie kluczy i wartości dowolnego typu, można użyć Dictionary<TKey,TValue> klasy ogólnej i określić typy dozwolone dla klucza i wartości. Wśród zalet typów ogólnych są zwiększone możliwości ponownego używania kodu i bezpieczeństwo typów.

Definiowanie i używanie typów ogólnych

Typy ogólne to klasy, struktury, interfejsy i metody, które mają symbole zastępcze (parametry typu) dla co najmniej jednego typu, które przechowują lub używają. Klasa kolekcji ogólnej może używać parametru typu jako symbolu zastępczego dla typu obiektów, które przechowuje; parametry typu są wyświetlane jako typy pól i typy parametrów jego metod. Metoda ogólna może używać parametru typu jako typu zwracanej wartości lub jako typu jednego z jego parametrów formalnych. Poniższy kod ilustruje prostą definicję klasy ogólnej.

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

Podczas tworzenia wystąpienia klasy ogólnej należy określić rzeczywiste typy, które mają zastąpić parametry typu. Spowoduje to utworzenie nowej klasy ogólnej, określanej jako skonstruowana klasa ogólna, z wybranymi typami zastąpionymi wszędzie tam, gdzie pojawiają się parametry typu. Wynik jest bezpieczną klasą, która jest dostosowana do wybranego typu, jak pokazano w poniższym kodzie.

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

Terminologia dotycząca typów ogólnych

Następujące terminy służą do omówienia typów ogólnych na platformie .NET:

  • Definicja typu ogólnego jest deklaracją klasy, struktury lub interfejsu, która działa jako szablon, z symbolami zastępczymi typów, które mogą zawierać lub używać. Na przykład System.Collections.Generic.Dictionary<TKey,TValue> klasa może zawierać dwa typy: klucze i wartości. Ponieważ definicja typu ogólnego jest tylko szablonem, nie można tworzyć wystąpień klasy, struktury lub interfejsu, który jest definicją typu ogólnego.

  • Parametry typu ogólnego lub parametry typu są symbolami zastępczymi w definicji typu ogólnego lub metody. Typ System.Collections.Generic.Dictionary<TKey,TValue> ogólny ma dwa parametry typu i TKeyTValue, które reprezentują typy jego kluczy i wartości.

  • Skonstruowany typ ogólny lub typ skonstruowany jest wynikiem określania typów dla parametrów typu ogólnego definicji typu.

  • Argument typu ogólnego jest dowolnym typem, który jest zastępowany dla parametru typu ogólnego.

  • Ogólny termin typ ogólny obejmuje zarówno typy konstruowane, jak i definicje typów ogólnych.

  • Kowariancja i kontrawariancja parametrów typu ogólnego umożliwiają używanie skonstruowanych typów ogólnych, których argumenty typu są bardziej pochodne (kowariancja) lub mniej pochodne (kontrawariancja) niż typ skonstruowany docelowy. Kowariancja i kontrawariancja są określane zbiorczo jako wariancja. Aby uzyskać więcej informacji, zobacz Covariance and Contravariance (Kowariancja i kontrawariancja).

  • Ograniczenia to limity nakładane na parametry typu ogólnego. Na przykład można ograniczyć parametr typu do typów, które implementują System.Collections.Generic.IComparer<T> interfejs ogólny, aby upewnić się, że wystąpienia typu mogą być uporządkowane. Można również ograniczyć parametry typu do typów, które mają określoną klasę bazową, które mają konstruktor bez parametrów lub które są typami referencyjnymi lub typami wartości. Użytkownicy typu ogólnego nie mogą zastąpić argumentów typu, które nie spełniają ograniczeń.

  • Definicja metody ogólnej jest metodą z dwoma listami parametrów: listą parametrów typu ogólnego i listą parametrów formalnych. Parametry typu mogą być wyświetlane jako typ zwracany lub jako typy parametrów formalnych, jak pokazano w poniższym kodzie.

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

Metody ogólne mogą pojawiać się w typach ogólnych lub niegenerycznych. Należy pamiętać, że metoda nie jest ogólna tylko dlatego, że należy do typu ogólnego, a nawet dlatego, że ma parametry formalne, których typy są ogólnymi parametrami otaczającego typu. Metoda jest ogólna tylko wtedy, gdy ma własną listę parametrów typu. W poniższym kodzie tylko metoda G jest ogólna.

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

Zalety i wady typów ogólnych

Korzystanie z kolekcji ogólnych i delegatów ma wiele zalet:

  • Bezpieczeństwo typów. Typy ogólne przenoszą obciążenie bezpieczeństwa typów od użytkownika do kompilatora. Nie ma potrzeby pisania kodu do testowania poprawnego typu danych, ponieważ jest on wymuszany w czasie kompilacji. Potrzeba rzutowania typu i możliwości błędów w czasie wykonywania jest ograniczona.

  • Mniejsze użycie kodu i kodu jest łatwiejsze do ponownego użycia. Nie ma potrzeby dziedziczenia po typie podstawowym i zastępowaniu elementów członkowskich. Na przykład element LinkedList<T> jest gotowy do natychmiastowego użycia. Można na przykład utworzyć połączoną listę ciągów z następującą deklaracją zmiennej:

    LinkedList<String^>^ llist = gcnew LinkedList<String^>();
    
    LinkedList<string> llist = new LinkedList<string>();
    
    Dim llist As New LinkedList(Of String)()
    
  • Lepsza wydajność. Typy kolekcji ogólnych zazwyczaj działają lepiej w przypadku przechowywania typów wartości i manipulowania nimi, ponieważ nie ma potrzeby tworzenia pól typów wartości.

  • Delegaty ogólne umożliwiają bezpieczne wywołania zwrotne typu bez konieczności tworzenia wielu klas delegatów. Na przykład Predicate<T> delegat ogólny pozwala utworzyć metodę, która implementuje własne kryteria wyszukiwania dla określonego typu i używać metody z metodami Array typu, takimi jak Find, FindLasti FindAll.

  • Typy ogólne usprawniają dynamicznie generowany kod. W przypadku używania typów ogólnych z dynamicznie generowanym kodem nie trzeba generować typu. Zwiększa to liczbę scenariuszy, w których można używać lekkich metod dynamicznych zamiast generowania całych zestawów. Aby uzyskać więcej informacji, zobacz How to: Define and Execute Dynamic Methods and DynamicMethod.

Poniżej przedstawiono pewne ograniczenia dotyczące typów ogólnych:

  • Typy ogólne mogą pochodzić z większości klas bazowych, takich jak (i ograniczenia mogą służyć do wymagania, że parametry typu ogólnego pochodzą z klas bazowych, takich jak MarshalByRefObjectMarshalByRefObject). Jednak platforma .NET nie obsługuje typów ogólnych powiązanych kontekstowo. Typ ogólny może pochodzić z ContextBoundObjectklasy , ale próba utworzenia wystąpienia tego typu powoduje wystąpienie klasy TypeLoadException.

  • Wyliczenia nie mogą mieć parametrów typu ogólnego. Wyliczenie może być ogólne tylko przypadkowo (na przykład dlatego, że jest zagnieżdżone w typie ogólnym zdefiniowanym przy użyciu Visual Basic, C# lub C++). Aby uzyskać więcej informacji, zobacz "Wyliczenia" w systemie typowych.

  • Lekkie metody dynamiczne nie mogą być ogólne.

  • W Visual Basic, C# i C++, zagnieżdżony typ, który jest ujęty w typ ogólny, nie można utworzyć wystąpienia, chyba że typy zostały przypisane do parametrów typu wszystkich ujęć typów. Innym sposobem na powiedzenie jest to, że w odbiciu zagnieżdżony typ zdefiniowany przy użyciu tych języków obejmuje parametry typu wszystkich jego otaczającego typu. Umożliwia to używanie parametrów typu otaczającego typów w definicjach składowych typu zagnieżdżonego. Aby uzyskać więcej informacji, zobacz "Zagnieżdżone typy" w programie MakeGenericType.

    Uwaga

    Zagnieżdżony typ zdefiniowany przez emitowanie kodu w zestawie dynamicznym lub przy użyciu Ilasm.exe (asembler IL) nie jest wymagany do uwzględnienia parametrów typu jego otaczającego typu; jednak jeśli nie zawiera ich, parametry typu nie znajdują się w zakresie w klasie zagnieżdżonej.

    Aby uzyskać więcej informacji, zobacz "Zagnieżdżone typy" w programie MakeGenericType.

Obsługa biblioteki klas i języka

Platforma .NET udostępnia wiele ogólnych klas kolekcji w następujących przestrzeniach nazw:

Interfejsy ogólne do implementowania porównań sortowania i równości są udostępniane w System przestrzeni nazw wraz z ogólnymi typami delegatów dla procedur obsługi zdarzeń, konwersji i predykatów wyszukiwania.

Obsługa typów ogólnych została dodana do System.Reflection przestrzeni nazw w celu badania typów ogólnych i metod ogólnych w celu System.Reflection.Emit emitowania zestawów dynamicznych zawierających typy ogólne i metody oraz generowanie System.CodeDom grafów źródłowych zawierających typy ogólne.

Środowisko uruchomieniowe języka wspólnego udostępnia nowe kody operacyjne i prefiksy do obsługi typów ogólnych w języku MSIL firmy Microsoft, w tym Stelem, , LdelemUnbox_Any, Constrainedi Readonly.

Visual C++, C# i Visual Basic wszystkie zapewniają pełną obsługę definiowania i używania typów ogólnych. Aby uzyskać więcej informacji na temat obsługi języka, zobacz Typy ogólne w Visual Basic, Wprowadzenie do typów ogólnych i Omówienie typów ogólnych w programie Visual C++.

Zagnieżdżone typy i typy ogólne

Typ zagnieżdżony w typie ogólnym może zależeć od parametrów typu otaczającego typu ogólnego. Środowisko uruchomieniowe języka wspólnego uznaje za zagnieżdżone typy jako ogólne, nawet jeśli nie mają własnych parametrów typu ogólnego. Podczas tworzenia wystąpienia typu zagnieżdżonego należy określić argumenty typu dla wszystkich ujęć typów ogólnych.

Tytuł Opis
Kolekcje ogólne na platformie .NET Opisuje ogólne klasy kolekcji i inne typy ogólne na platformie .NET.
Delegaty ogólne do manipulowania tablicami i listami Opisuje delegatów ogólnych konwersji, predykatów wyszukiwania i akcji do wykonania na elementach tablicy lub kolekcji.
Interfejsy ogólne Opisuje interfejsy ogólne, które zapewniają typowe funkcje w różnych rodzinach typów ogólnych.
Kowariancja i kontrawariancja Opisuje kowariancję i kontrawariancję w parametrach typu ogólnego.
Często używane typy kolekcji Zawiera podsumowanie informacji na temat charakterystyk i scenariuszy użycia typów kolekcji na platformie .NET, w tym typów ogólnych.
Kiedy należy używać kolekcji ogólnych Opisuje ogólne reguły określania, kiedy należy używać typów kolekcji ogólnych.
Instrukcje: Definiowanie typu ogólnego przy użyciu emisji odbicia Wyjaśnia sposób generowania zestawów dynamicznych, które obejmują typy ogólne i metody.
Typy ogólne w Visual Basic Opisuje funkcję ogólne dla użytkowników Visual Basic, w tym tematy z instrukcjami dotyczącymi używania i definiowania typów ogólnych.
Wprowadzenie do typów ogólnych Zawiera omówienie definiowania i używania typów ogólnych dla użytkowników języka C#.
Omówienie typów ogólnych w języku Visual C++ Opisuje funkcję ogólne dla użytkowników języka C++, w tym różnice między rodzajami ogólnymi i szablonami.

Tematy pomocy

System.Collections.Generic

System.Collections.ObjectModel

System.Reflection.Emit.OpCodes