Udostępnij za pośrednictwem


Instrukcje: zwiększanie wydajności za pomocą typów ogólnych (C++/CLI)

W przypadku typów ogólnych można utworzyć kod wielokrotnego użytku na podstawie parametru typu. Rzeczywisty typ parametru typu jest odroczony do momentu wywołania przez kod klienta. Aby uzyskać więcej informacji na temat typów ogólnych, zobacz Ogólne.

W tym artykule omówiono, w jaki sposób typy ogólne mogą pomóc zwiększyć wydajność aplikacji korzystającej z kolekcji.

Przykład: dwie główne wady kolekcji programu .NET Framework

Program .NET Framework zawiera wiele klas kolekcji w System.Collections przestrzeni nazw. Większość z tych kolekcji działa na obiektach typu System.Object. Kolekcje mogą przechowywać dowolny typ, ponieważ wszystkie typy w programie .NET Framework, nawet typy wartości, pochodzą z klasy System.Object. Istnieją jednak dwie wady tego podejścia.

Po pierwsze, jeśli kolekcja przechowuje typy wartości, takie jak liczby całkowite, przed dodaniu wartości do kolekcji i rozpakowaniu, gdy wartość zostanie pobrana z kolekcji. Te operacje są kosztowne.

Po drugie, nie ma możliwości kontrolowania typów, które można dodać do kolekcji. Jest to całkowicie legalne, aby dodać liczbę całkowitą i ciąg do tej samej kolekcji, mimo że prawdopodobnie nie jest to, co było zamierzone. W związku z tym, aby kod był bezpieczny, musisz sprawdzić, czy typ pobrany z kolekcji naprawdę jest oczekiwany.

Poniższy przykład kodu przedstawia dwie główne wady kolekcji programu .NET Framework przed rodzajami.

// perf_pre_generics.cpp
// compile with: /clr

using namespace System;
using namespace System::Collections;

int main()
{
    // This Stack can contain any type.
    Stack ^s = gcnew Stack();

    // Push an integer to the Stack.
    // A boxing operation is performed here.
    s->Push(7);

    // Push a String to the same Stack.
    // The Stack now contains two different data types.
    s->Push("Seven");

    // Pop the items off the Stack.
    // The item is returned as an Object, so a cast is
    // necessary to convert it to its proper type.
    while (s->Count> 0)
    {
        Object ^o = s->Pop();
        if (o->GetType() == Type::GetType("System.String"))
        {
            Console::WriteLine("Popped a String: {0}", (String ^)o);
        }
        else if (o->GetType() == Type::GetType("System.Int32"))
        {
            Console::WriteLine("Popped an int: {0}", (int)o);
        }
        else
        {
            Console::WriteLine("Popped an unknown type!");
        }
    }
}
Popped a String: Seven
Popped an int: 7

Przykład: Korzyść użycia kolekcji ogólnej

Nowa System.Collections.Generic przestrzeń nazw zawiera wiele z tych samych kolekcji znalezionych w System.Collections przestrzeni nazw, ale zostały zmodyfikowane tak, aby akceptowały parametry typu ogólnego. Ta zmiana eliminuje dwie wady kolekcji innych niż ogólne: boxing i rozpakowywanie typów wartości oraz brak możliwości określenia typów, które mają być przechowywane w kolekcjach. Operacje na dwóch kolekcjach są identyczne; różnią się one tylko tym, jak są tworzone.

Porównaj przykład napisany powyżej z tym przykładem, który używa kolekcji ogólnej Stack<T> . W przypadku dużych kolekcji, które są często używane, wydajność tego przykładu będzie znacznie większa niż w poprzednim przykładzie.

// perf_post_generics.cpp
// compile with: /clr

#using <System.dll>

using namespace System;
using namespace System::Collections::Generic;

int main()
{
    // This Stack can only contain integers.
    Stack<int> ^s = gcnew Stack<int>();

    // Push an integer to the Stack<int>.
    // No boxing operation is performed here.
    s->Push(7);
    s->Push(14);

    // You can no longer push a String to the same Stack.
    // This will result in compile time error C2664.
    //s->Push("Seven");

    // Pop an item off the Stack.
    // The item is returned as the type of the collection, so no
    // casting is necessary and no unboxing is performed for
    // value types.
    int i = s->Pop();
    Console::WriteLine(i);

    // You can no longer retrieve a String from the Stack.
    // This will result in compile time error C2440.
    //String ^str = s->Pop();
}
14

Zobacz też

Typy ogólne