Udostępnij za pomocą


Typy ogólne na platformie .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 jest zwiększona możliwość 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 przechowywanych obiektów. 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.

public class SimpleGenericClass<T>
{
    public T Field;
}
Public Class SimpleGenericClass(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. Wynikiem jest klasa bezpieczna typowo, dopasowana do wybranych przez użytkownika typów, jak pokazano w poniższym kodzie.

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

Terminologia

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

  • Definicja typu ogólnego to deklaracja klasy, struktury lub interfejsu, która pełni rolę szablonu, posiadając miejsca dla typów, które może 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.

  • Ogólne parametry typu 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, TKey i TValue, które reprezentują typy kluczy i wartości.

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

  • Argument typu ogólnego to dowolny typ, który jest zastępowany dla parametru typu ogólnego.

  • Ogólny typ ogólny obejmuje zarówno typy skonstruowane, 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ą łącznie określane jako wariancja. Aby uzyskać więcej informacji, zobacz 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 dwiema 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.

    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
    

    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.

    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
    

Zalety i wady typów ogólnych

Stosowanie kolekcji ogólnych i delegatów oferuje wiele zalet:

  • Bezpieczeństwo typu. Typy ogólne przenoszą obciążenie bezpieczeństwa typu od Ciebie do kompilatora. Nie ma potrzeby pisania kodu w celu przetestowania prawidłowego typu danych, ponieważ jest on wymuszany w czasie kompilacji. Potrzeba rzutowania typów i ryzyko wystąpienia błędów w czasie wykonania są zmniejszone.

  • Mniej kodu, który jest łatwiejszy do ponownego użycia. Nie ma potrzeby dziedziczenia po typie podstawowym i nadpisywania członków. 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 = new LinkedList<string>();
    
    Dim llist As New LinkedList(Of String)()
    
  • Lepsza wydajność. Typy kolekcji ogólnych zwykle lepiej radzą sobie z przechowywaniem typów wartości i manipulowaniem nimi, ponieważ nie ma potrzeby tworzenia pól 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 umożliwia utworzenie metody, która implementuje własne kryteria wyszukiwania dla określonego typu i pozwala używać tej metody z metodami typu Array, takimi jak Find, FindLast, i 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 ogólne parametry typu 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 być pochodną ContextBoundObject, ale próba utworzenia wystąpienia tego typu powoduje 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 języka Visual Basic, C#lub C++). Aby uzyskać więcej informacji, zobacz "Wyliczenia" w Systemie Typów Wspólnych.

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

  • W języku Visual Basic, C# i C++ nie można utworzyć wystąpienia zagnieżdżonego typu ujętego w typ ogólny, chyba że typy zostały przypisane do parametrów typu wszystkich otaczających typów. Innym sposobem wyrażenia tego jest to, że w kontekście refleksji zagnieżdżony typ zdefiniowany przy użyciu tych języków obejmuje parametry typu wszystkich swoich obejmujących typów. Dzięki temu parametry typu otaczającego typów mogą być używane w definicjach składowych typu zagnieżdżonego. Więcej informacji znajdziesz w "Zagnieżdżone typy" w pliku MakeGenericType.

    Uwaga

    Typ zagnieżdżony zdefiniowany przez emitowanie kodu w dynamicznej asemblaży lub przy użyciu Ilasm.exe (asembler IL) nie jest zobowiązany do uwzględnienia parametrów typów swoich otaczających typów; jednak jeśli ich nie zawiera, parametry typów nie są dostępne w zagnieżdżonej klasie.

    Więcej informacji znajdziesz w "Zagnieżdżone typy" w pliku MakeGenericType.

Obsługa biblioteki klas i języka

Platforma .NET udostępnia szereg 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.

System.Numerics Przestrzeń nazw udostępnia ogólne interfejsy dla funkcji matematycznych (dostępnych na platformie .NET 7 i nowszych wersjach). Aby uzyskać więcej informacji, zobacz Ogólne obliczenia matematyczne.

Obsługa typów ogólnych została dodana do przestrzeni nazw System.Reflection w celu badania typów ogólnych i metod ogólnych, do System.Reflection.Emit w celu emitowania zestawów dynamicznych zawierających typy i metody ogólne, oraz do System.CodeDom w celu generowania grafów źródłowych obejmują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 typowym języku pośrednim (CIL), w tym Stelem, Ldelem, Unbox_Any, Constrained i Readonly.

Visual C++, C# i Visual Basic 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 języku 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 otaczającego typu ogólnego. Środowisko uruchomieniowe języka wspólnego traktuje typy zagnieżdżone jako generyczne, nawet jeśli nie mają własnych parametrów typu generycznego. Podczas tworzenia wystąpienia typu zagnieżdżonego należy określić parametry typów dla wszystkich otaczających typów generycznych.

Nazwa 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 ogólne delegaty do konwersji, predykaty wyszukiwania i działania do wykonania na elementach tablicy lub kolekcji.
Ogólna matematyka Opisuje sposób wykonywania operacji matematycznych w sposób ogólny.
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 z emitem odbicia Objaśnienie sposobu generowania zestawów dynamicznych obejmujących typy ogólne i metody.
Typy ogólne w Visual Basic Opisuje funkcję rodzajową dla użytkowników języka Visual Basic, w tym tematy z instrukcjami dotyczącymi używania i definiowania typów ogólnych.
Wprowadzenie do typów generycznych 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 programie Visual C++ Opisuje funkcję rodzajową dla użytkowników języka C++, w tym różnice między rodzajami ogólnymi i szablonami.

Źródło