Generics in de runtime (C#-programmeerhandleiding)
Wanneer een algemeen type of methode wordt gecompileerd in algemene tussenliggende taal (CIL), bevat het metagegevens die het identificeren als typeparameters. De manier waarop het CIL voor een algemeen type wordt gebruikt, verschilt op basis van of de opgegeven typeparameter een waardetype of verwijzingstype is.
Wanneer een algemeen type voor het eerst wordt samengesteld met een waardetype als parameter, maakt de runtime een speciaal algemeen type met de opgegeven parameter of parameters die worden vervangen op de juiste locaties in de CIL. Gespecialiseerde algemene typen worden één keer gemaakt voor elk uniek waardetype dat wordt gebruikt als parameter.
Stel dat uw programmacode een stack heeft gedeclareerd die bestaat uit gehele getallen:
Stack<int>? stack;
Op dit moment genereert de runtime een gespecialiseerde versie van de Stack<T> klasse die het gehele getal heeft vervangen door de parameter. Wanneer uw programmacode nu gebruikmaakt van een stapel gehele getallen, gebruikt de runtime de gegenereerde gespecialiseerde Stack<T> klasse opnieuw. In het volgende voorbeeld worden twee exemplaren van een stapel gehele getallen gemaakt en delen ze één exemplaar van de Stack<int>
code:
Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();
Stel dat een andere Stack<T> klasse met een ander waardetype, zoals een long
of een door de gebruiker gedefinieerde structuur als de parameter, op een ander punt in uw code wordt gemaakt. Als gevolg hiervan genereert de runtime een andere versie van het algemene type en vervangt een long
in de juiste locaties in CIL. Conversies zijn niet meer nodig omdat elke gespecialiseerde algemene klasse systeemeigen het waardetype bevat.
Generics werken enigszins anders voor referentietypen. De eerste keer dat een algemeen type wordt samengesteld met elk verwijzingstype, maakt de runtime een gespecialiseerd algemeen type met objectverwijzingen die worden vervangen door de parameters in de CIL. Telkens wanneer een geconstrueerd type wordt geïnstantieerd met een verwijzingstype als parameter, ongeacht het type, gebruikt de runtime de eerder gemaakte gespecialiseerde versie van het algemene type opnieuw. Dit is mogelijk omdat alle verwijzingen dezelfde grootte hebben.
Stel dat u twee verwijzingstypen hebt, een Customer
klasse en een Order
klasse, en stel ook dat u een stapel typen Customer
hebt gemaakt:
class Customer { }
class Order { }
Stack<Customer> customers;
Op dit moment genereert de runtime een gespecialiseerde versie van de Stack<T> klasse waarin objectverwijzingen worden opgeslagen die later worden ingevuld in plaats van gegevens op te slaan. Stel dat met de volgende regel code een stack van een ander referentietype wordt gemaakt, die de naam Order
heeft:
Stack<Order> orders = new Stack<Order>();
In tegenstelling tot waardetypen wordt er geen gespecialiseerde versie van de Stack<T> klasse gemaakt voor het Order
type. In plaats daarvan wordt een exemplaar van de gespecialiseerde versie van de Stack<T> klasse gemaakt en wordt de orders
variabele ingesteld om ernaar te verwijzen. Stel dat u vervolgens een coderegel hebt aangetroffen om een stack van een Customer
type te maken:
customers = new Stack<Customer>();
Net als bij het vorige gebruik van de Stack<T> klasse die is gemaakt met behulp van het Order
type, wordt er een ander exemplaar van de gespecialiseerde Stack<T> klasse gemaakt. De aanwijzers die daarin zijn opgenomen, zijn ingesteld om te verwijzen naar een geheugengebied dat de grootte van een Customer
type heeft. Omdat het aantal referentietypen sterk kan variëren van programma tot programma, vermindert de C#-implementatie van generieken de hoeveelheid code aanzienlijk door het aantal gespecialiseerde klassen te verminderen dat door de compiler is gemaakt voor algemene referentietypen.
Bovendien, wanneer een algemene C#-klasse wordt geïnstantieerd met behulp van een waardetype of referentietypeparameter, kan reflectie deze tijdens runtime opvragen en zowel het werkelijke type als de bijbehorende typeparameter kunnen worden vastgesteld.