Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med generiska objekt kan du skräddarsy en metod, klass, struktur eller ett gränssnitt efter den exakta datatyp som den fungerar på. I stället för att till exempel använda Hashtable klassen, som gör att nycklar och värden kan vara av valfri typ, kan du använda den Dictionary<TKey,TValue> generiska klassen och ange vilka typer som tillåts för nyckeln och värdet. Bland fördelarna med generiska läkemedel finns ökad kodåteranvändning och typsäkerhet.
Definiera och använda generiska data
Generiska objekt är klasser, strukturer, gränssnitt och metoder som har platshållare (typparametrar) för en eller flera av de typer som de lagrar eller använder. En allmän samlingsklass kan använda en typparameter som platshållare för den typ av objekt som den lagrar. Typparametrarna visas som typer av fält och parametertyperna för dess metoder. En allmän metod kan använda sin typparameter som typ av dess returvärde eller som typ av en av dess formella parametrar.
Följande kod illustrerar en enkel allmän klassdefinition.
public class SimpleGenericClass<T>
{
public T Field;
}
Public Class SimpleGenericClass(Of T)
Public Field As T
End Class
När du skapar en instans av en allmän klass anger du de faktiska typerna som ska ersätta typparametrarna. Detta etablerar en ny generisk klass, som kallas en konstruerad generisk klass, där dina valda typer ersätts överallt där typparametrarna visas. Resultatet är en typsäker klass som är skräddarsydd för ditt val av typer, vilket visas i följande kod.
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
Terminologi
Följande termer används för att diskutera generiska läkemedel i .NET:
En allmän typdefinition är en klass-, struktur- eller gränssnittsdeklaration som fungerar som en mall, med platshållare för de typer som den kan innehålla eller använda. Klassen kan till exempel System.Collections.Generic.Dictionary<TKey,TValue> innehålla två typer: nycklar och värden. Eftersom en allmän typdefinition bara är en mall kan du inte skapa instanser av en klass, struktur eller ett gränssnitt som är en allmän typdefinition.
Generiska typparametrar, eller typparametrar, är platshållarna i en allmän typ eller metoddefinition. Den System.Collections.Generic.Dictionary<TKey,TValue> generiska typen har två typparametrar och
TKeyTValue, som representerar typerna av dess nycklar och värden.En konstruerad allmän typ, eller en konstruerad typ, är resultatet av att ange typer för parametrar av allmän typ i en generisk typdefinition.
Ett generiskt typargument är en typ som ersätts med en generisk typparameter.
Den allmänna termen allmän typ innehåller både konstruerade typer och generiska typdefinitioner.
Med kovarians och kontravarians för generiska typparametrar kan du använda konstruerade generiska typer vars typargument är mer härledda (kovarians) eller mindre härledda (kontravarians) än en målkonstruerad typ. Kovarians och kontravariation kallas gemensamt varians. Mer information finns i Covariance och contravariance.
Begränsningar är gränser för generiska typparametrar. Du kan till exempel begränsa en typparameter till typer som implementerar det System.Collections.Generic.IComparer<T> allmänna gränssnittet för att säkerställa att instanser av typen kan ordnas. Du kan också begränsa typparametrar till typer som har en viss basklass, som har en parameterlös konstruktor eller som är referenstyper eller värdetyper. Användare av den allmänna typen kan inte ersätta typargument som inte uppfyller begränsningarna.
En allmän metoddefinition är en metod med två parameterlistor: en lista med generiska typparametrar och en lista över formella parametrar. Typparametrar kan visas som returtyp eller som typerna av de formella parametrarna, som följande kod visar.
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 FunctionGeneriska metoder kan visas på generiska eller icke-generiska typer. Det är viktigt att observera att en metod inte är generisk bara för att den tillhör en generisk typ, eller till och med för att den har formella parametrar vars typer är de generiska parametrarna för den omslutande typen. En metod är endast generisk om den har en egen lista med typparametrar. I följande kod är endast metoden
Ggenerisk.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
Fördelar och nackdelar med generiska läkemedel
Det finns många fördelar med att använda allmänna samlingar och ombud:
Typsäkerhet. Generics flyttar ansvaret för typsäkerhet från dig till kompilatorn. Det finns ingen anledning att skriva kod för att testa för rätt datatyp eftersom den framtvingas vid kompileringstillfället. Behovet av typgjutning och risken för körningsfel minskar.
Mindre kod och kod återanvänds enklare. Det finns inget behov av att ärva från en bastyp och åsidosätta medlemmar. Till exempel LinkedList<T> är redo för omedelbar användning. Du kan till exempel skapa en länkad lista med strängar med följande variabeldeklaration:
LinkedList<string> llist = new LinkedList<string>();Dim llist As New LinkedList(Of String)()Bättre prestanda. Allmänna samlingstyper fungerar vanligtvis bättre för att lagra och manipulera värdetyper eftersom det inte finns något behov av att boxa värdetyperna.
Allmänna ombud aktiverar typsäkra återanrop utan att behöva skapa flera ombudsklasser. Med den generiska delegaten Predicate<T> kan du till exempel skapa en metod som implementerar dina egna sökkriterier för en viss typ och använda din metod med metoder av typen Array såsom Find, FindLast och FindAll.
Generika effektiviserar dynamiskt genererad kod. När du använder generiska objekt med dynamiskt genererad kod behöver du inte generera typen. Detta ökar antalet scenarier där du kan använda lätta dynamiska metoder i stället för att generera hela sammansättningar. Mer information finns i Så här definierar och kör du dynamiska metoder och DynamicMethod.
Följande är några begränsningar för generiska läkemedel:
Generiska typer kan härledas från de flesta basklasser, till exempel MarshalByRefObject (och begränsningar kan användas för att kräva att generiska typparametrar härleds från basklasser som MarshalByRefObject). .NET stöder dock inte kontextbundna generiska typer. En allmän typ kan härledas från ContextBoundObject, men om du försöker skapa en instans av den typen får du en TypeLoadException.
Uppräkningar kan inte ha generiska typparametrar. En uppräkning kan endast vara generisk för övrigt (till exempel eftersom den är kapslad i en allmän typ som definieras med Visual Basic, C#eller C++). Mer information finns i "Uppräkningar" i Common Type System.
Lätta dynamiska metoder kan inte vara generiska.
I Visual Basic, C#och C++kan en kapslad typ som omges av en allmän typ inte instansieras om inte typer har tilldelats typparametrarna för alla omslutande typer. Ett annat sätt att säga detta är att i eftertanke innehåller en kapslad typ som definieras med hjälp av dessa språk typparametrar för alla dess omslutande typer. På så sätt kan typparametrarna för omslutande typer användas i medlemsdefinitionerna av en kapslad typ. Mer information finns i "Kapslade typer" i MakeGenericType.
Anmärkning
En kapslad typ som definieras genom att generera kod i en dynamisk sammansättning eller med hjälp av Ilasm.exe (IL Assembler) krävs inte för att inkludera typparametrarna för dess omslutande typer. Men om den inte innehåller dem finns typparametrarna inte i omfånget i den kapslade klassen.
Mer information finns i "Kapslade typer" i MakeGenericType.
Stöd för klassbibliotek och språk
.NET tillhandahåller ett antal generiska samlingsklasser i följande namnområden:
Namnområdet System.Collections.Generic innehåller de flesta av de generiska samlingstyperna som tillhandahålls av .NET, till exempel de List<T> allmänna klasserna och Dictionary<TKey,TValue> .
Namnområdet System.Collections.ObjectModel innehåller ytterligare generiska samlingstyper, till exempel den ReadOnlyCollection<T> generiska klassen, som är användbara för att exponera objektmodeller för användare av dina klasser.
Allmänna gränssnitt för implementering av sorterings- och likhetsjämförelser finns i System namnområdet, tillsammans med allmänna ombudstyper för händelsehanterare, konverteringar och sökpredikat.
Namnområdet System.Numerics innehåller allmänna gränssnitt för matematiska funktioner (tillgängliga i .NET 7 och senare versioner). Mer information finns i Allmän matematik.
Stöd för generiska objekt har lagts till i System.Reflection namnområdet för att undersöka generiska typer och generiska metoder, för att System.Reflection.Emit generera dynamiska sammansättningar som innehåller generiska typer och metoder samt för att System.CodeDom generera källdiagram som innehåller generiska objekt.
Den vanliga språkkörningen i Common Language Runtime innehåller nya opcodes och prefix för att stödja generiska typer på vanligt mellanliggande språk (CIL), inklusive Stelem, Ldelem, Unbox_Any, Constrained, och Readonly.
Visual C++, C#och Visual Basic har alla fullt stöd för att definiera och använda generiska objekt. Mer information om språkstöd finns i Allmänna typer i Visual Basic, Introduktion till generiska objekt och Översikt över generiska objekt i Visual C++.
Kapslade typer och generiska objekt
En typ som är kapslad i en allmän typ kan bero på typparametrarna för den omslutande generiska typen. Den gemensamma språkens exekveringsmiljö betraktar kapslade typer som generiska, även om de inte har egna generiska typparametrar. När du skapar en instans av en kapslad typ måste du ange typargument för alla omslutande generiska typer.
Relaterade artiklar
| Titel | Beskrivning |
|---|---|
| Generiska samlingar i .NET | Beskriver generiska samlingsklasser och andra generiska typer i .NET. |
| Generiska delegationer för att hantera arrayer och listor | Beskriver generiska delegater för konverteringar, sökpredikat och åtgärder som ska vidtas på element i en matris eller samlingar. |
| Allmän matematik | Beskriver hur du kan utföra matematiska operationer allmänt. |
| Allmänna gränssnitt | Beskriver allmänna gränssnitt som ger vanliga funktioner i familjer av generiska typer. |
| Kovarians och kontravarians | Beskriver kovarians och kontravarians i generiska typparametrar. |
| Samlingstyper som används ofta | Innehåller sammanfattningsinformation om egenskaperna och användningsscenarierna för samlingstyperna i .NET, inklusive generiska typer. |
| När du ska använda allmänna samlingar | Beskriver allmänna regler för att avgöra när generiska samlingstyper ska användas. |
| Gör så här: Definiera en generisk typ med Reflection.Emit | Förklarar hur du genererar dynamiska sammansättningar som innehåller generiska typer och metoder. |
| Allmänna typer i Visual Basic | Beskriver generell funktion för Visual Basic-användare, inklusive instruktioner för att använda och definiera generiska typer. |
| Introduktion till generiska läkemedel | Ger en översikt över hur du definierar och använder allmänna typer för C#-användare. |
| Översikt över generiska objekt i Visual C++ | Beskriver funktionen generics för C++-användare, inklusive skillnaderna mellan generiska objekt och mallar. |