Allmänna typer i Visual Basic (Visual Basic)
En allmän typ är ett enda programmeringselement som anpassas för att utföra samma funktioner för flera datatyper. När du definierar en allmän klass eller procedur behöver du inte definiera en separat version för varje datatyp som du kanske vill utföra den funktionen för.
En analogi är en skruvmejseluppsättning med flyttbara huvuden. Du inspekterar skruven och väljer rätt huvud för den skruven (skårad, korsad, stjärnmärkt). När du sätter in rätt huvud i skruvmejselhandtaget utför du exakt samma funktion med skruvmejseln, nämligen att vrida skruven.
När du definierar en allmän typ kan du parametrisera den med en eller flera datatyper. Med typparametrar kan kod skräddarsy datatyperna efter dess krav. Koden kan deklarera flera olika programmeringselement från det allmänna elementet, var och en som agerar på en annan uppsättning datatyper. Men de deklarerade elementen utför alla identisk logik, oavsett vilka datatyper de använder.
Du kanske till exempel vill skapa och använda en köklass som fungerar på en viss datatyp, till exempel String
. Du kan deklarera en sådan klass från System.Collections.Generic.Queue<T>, som i följande exempel visas.
Public stringQ As New System.Collections.Generic.Queue(Of String)
Nu kan du använda stringQ
för att arbeta uteslutande med String
värden. Eftersom stringQ
är specifikt för String
i stället för att generaliseras för Object
värden, har du inte sen bindning eller typkonvertering. Generiska typer sparar exekveringstid och minskar körfel.
Mer information om hur du använder en allmän typ finns i How to: Use a Generic Class.
Exempel på en allmän klass
I följande exempel visas en skelettdefinition av en generisk klass.
Public Class classHolder(Of t)
Public Sub processNewItem(ByVal newItem As t)
Dim tempItem As t
' Insert code that processes an item of data type t.
End Sub
End Class
I föregående skelett är t
en typparameter, det vill säga en platshållare för en datatyp som du anger när du deklarerar klassen. På andra ställen i koden kan du deklarera olika versioner av classHolder
genom att ange olika datatyper för t
. I följande exempel visas två sådana deklarationer.
Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)
Föregående instruktioner deklarerar konstruerade klasser, där en viss typ ersätter typparametern. Den här ersättningen propageras i koden i den konstruerade klassen. I följande exempel visas hur processNewItem
-proceduren ser ut i integerClass
.
Public Sub processNewItem(ByVal newItem As Integer)
Dim tempItem As Integer
' Inserted code now processes an Integer item.
End Sub
Ett mer komplett exempel finns i Så här: Definiera en klass som kan tillhandahålla identiska funktioner på olika datatyper.
Berättigade programmeringselement
Du kan definiera och använda allmänna klasser, strukturer, gränssnitt, procedurer och ombud. .NET definierar flera generiska klasser, strukturer och gränssnitt som representerar vanliga allmänna element. System.Collections.Generic-namnområdet innehåller ordlistor, listor, köer och staplar. Innan du definierar ett eget generiskt element ska du se om det redan är tillgängligt i System.Collections.Generic.
Procedurer är inte typer, men du kan definiera och använda allmänna procedurer. Se allmänna procedurer i Visual Basic.
Fördelar med generiska typer
En allmän typ fungerar som grund för att deklarera flera olika programmeringselement, som var och en fungerar med en specifik datatyp. Alternativen till en allmän typ är:
- En enda typ som körs på
Object
datatypen. - En samling typspecifika versioner av typen. Varje version kodas individuellt och körs på en specifik datatyp, till exempel
String
,Integer
eller en användardefinierad typ, till exempelcustomer
.
En allmän typ har följande fördelar jämfört med dessa alternativ:
- Typsäkerhet. Allmänna typer tillämpar kompileringstidstypkontroll. Typer baserade på
Object
accepterar alla datatyper och du måste skriva kod för att kontrollera om en indatatyp är acceptabel. Med generiska typer kan kompilatorn fånga typmissmatchningar före exekvering. - Föreställning. Allmänna typer behöver inte boxa och avboxa data eftersom varje är specialiserad på en specifik datatyp. Åtgärder baserade på
Object
måste boxa indatatyper för att konvertera dem tillObject
och avboxa data som är avsedda för utdata. Boxning och avboxning minskar prestandan. Typer baserade påObject
är också senbunda, vilket innebär att åtkomst till deras medlemsfunktioner kräver extra kod vid körning. Typkonverteringar minskar också prestandan. - Kodkonsolidering. Koden i en allmän typ måste bara definieras en gång. En uppsättning typspecifika versioner av en typ måste replikera samma kod i varje version, där den enda skillnaden är den specifika datatypen för den versionen. Med generiska typer genereras alla typspecifika versioner från den ursprungliga generiska typen.
- Återanvänd kod. Kod som inte är beroende av en viss datatyp kan återanvändas med olika datatyper om den är generisk. Du kan ofta återanvända den även med en datatyp som du inte förutsade från början.
- IDE-support. När du använder en konstruerad typ som deklarerats från en allmän typ kan den integrerade utvecklingsmiljön (IDE) ge dig mer stöd när du utvecklar koden. IntelliSense kan till exempel visa de typspecifika alternativen för ett argument till en konstruktor eller metod.
- Allmänna algoritmer. Abstrakta algoritmer som är typoberoende är bra kandidater för generiska typer. En allmän procedur som sorterar objekt med hjälp av IComparable-gränssnittet kan till exempel användas med alla datatyper som implementerar IComparable.
Begränsningar
Även om koden i en allmän typdefinition ska vara så typoberoende som möjligt, kan du behöva kräva en viss funktion av alla datatyper som tillhandahålls till den allmänna typen. Om du till exempel vill jämföra två poster för att sortera eller sammanställa, måste deras datatyp implementera IComparable-gränssnittet. Du kan tillämpa det här kravet genom att lägga till en begränsning till typparametern.
Exempel på en begränsning
I följande exempel visas en skelettdefinition av en klass med en begränsning som kräver typargumentet för att implementera IComparable.
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
Om efterföljande kod försöker konstruera en klass från itemManager
som anger en typ som inte implementerar IComparable, signalerar kompilatorn ett fel.
Typer av begränsningar
Din begränsning kan ange följande krav i valfri kombination:
- Typargumentet måste implementera ett eller flera gränssnitt
- Typargumentet måste vara av typen av, eller ärva från, högst en klass
- Typargumentet måste exponera en parameterlös konstruktor som är tillgänglig för koden som skapar objekt från den
- Typargumentet måste vara en referenstyp, eller så måste det vara en värdetyp
C#-kod kan deklarera att ett typargument måste vara en ohanterad typ. Visual Basic tillämpar den här begränsningen för Visual Basic-kod som använder en allmän typ eller metod som har definierats med den här begränsningen (i C#). Du kan dock inte deklarera en unmanaged
begränsning för en typparameter i Visual Basic.
Om du behöver införa fler än ett krav använder du en kommaavgränsad begränsningslista inuti klammerparenteser ({ }
). Om du vill kräva en tillgänglig konstruktor tar du med nyckelordet Ny operator i listan. Om du vill kräva en referenstyp inkluderar du nyckelordet Class
. för att kräva en värdetyp inkluderar du nyckelordet Structure
.
Mer information om begränsningar finns i typlista.
Exempel på flera begränsningar
I följande exempel visas en skelettdefinition av en generisk klass med en begränsningslista för typparametern. I koden som skapar en instans av den här klassen måste typargumentet implementera både IComparable- och IDisposable-gränssnitten, vara en referenstyp och exponera en tillgänglig parameterlös konstruktor.
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
Viktiga termer
Generiska typer introducerar och använder följande termer:
- allmän typ. En definition av en klass, struktur, gränssnitt, procedur eller ombud som du anger minst en datatyp för när du deklarerar den.
- Typparameter. I en definition av en generell typ är det en platshållare för en datatyp som du anger när du deklarerar typen.
- Typ-argument. En specifik datatyp som ersätter en typparameter när du deklarerar en konstruerad typ från en allmän typ.
- begränsning. Ett villkor för en typparameter som begränsar det typargument som du kan ange för den. En begränsning kan kräva att typargumentet implementerar ett visst gränssnitt, ärver från en viss klass, har en tillgänglig parameterlös konstruktor eller är en referenstyp eller en värdetyp. Du kan kombinera dessa begränsningar, men du kan ange högst en basklass.
- Konstruerad typ. En klass, struktur, gränssnitt, procedur eller ombud som deklarerats från en allmän typ genom att ange typargument för sina typparametrar.