Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Oorzaak
Methoden voor algemene typen en algemene methoden die worden geïnstantieerd over verschillende typen, worden ondersteund door verschillende systeemeigen codeteksten die zijn gespecialiseerd voor de opgegeven typeparameter.
Het is mogelijk om een cyclus te vormen tussen generieke instanties zodanig dat het aantal systeemeigen code-instanties dat nodig is om de toepassing te ondersteunen, onbeperkt wordt. Omdat systeemeigen AOT-implementaties vereisen dat alle systeemeigen methodeteksten worden gegenereerd op het moment dat de toepassing wordt gepubliceerd, zou dit een oneindig aantal methoden moeten compileren.
Wanneer het AOT-compilatieproces dergelijke ongebreidelde groei detecteert, stopt het de groei door een gooimethode te genereren. Als de toepassing het grenspunt tijdens runtime overschrijdt, wordt er een uitzondering gegenereerd.
Hoewel het onwaarschijnlijk is dat het uitvoerende deel van de werpende methode tijdens uitvoering wordt bereikt, is het raadzaam om de generieke recursie te verwijderen door de code te herstructureren. Algemene recursie heeft een negatieve invloed op de compilatiesnelheid en de grootte van het uitvoerbare bestand.
In .NET wordt generieke code die is geïnstantieerd met een referentietype gedeeld voor alle referentietype-instanteringen (bijvoorbeeld de code om List<string> en List<object> te ondersteunen is hetzelfde). Er zijn echter aanvullende systeemeigen gegevensstructuren nodig om de 'algemene context' uit te drukken (het ding dat wordt vervangen door T). Het is ook mogelijk om algemene recursie te vormen binnen deze gegevensstructuren. Dit kan bijvoorbeeld gebeuren als de algemene context moet verwijzen naar Foo<Foo<T>>, die op zijn beurt Foo<Foo<Foo<T>>> nodig heeft.
Example
Het volgende programma werkt correct voor invoer '2', maar genereert een uitzondering voor invoer '100'.
// AOT analysis warning IL3054:
// Program.<<Main>$>g__CauseGenericRecursion|0_0<Struct`1<Struct`1<Struct`1<Struct`1<Int32>>>>>(Int32):
// Generic expansion to 'Program.<<Main>$>g__CauseGenericRecursion|0_0<Struct`1<Struct`1<Struct`1<Struct`1<Struct`1<Int32>>>>>>(Int32)'
// was aborted due to generic recursion. An exception will be thrown at runtime if this codepath
// is ever reached. Generic recursion also negatively affects compilation speed and the size of
// the compilation output. It is advisable to remove the source of the generic recursion
// by restructuring the program around the source of recursion. The source of generic recursion
// might include: 'Program.<<Main>$>g__CauseGenericRecursion|0_0<T>(Int32)
using System;
int number = int.Parse(Console.ReadLine());
Console.WriteLine(CauseGenericRecursion<int>(number));
static int CauseGenericRecursion<T>(int i) => 1 + CauseGenericRecursion<Struct<T>>(i - 1);
struct Struct<T> { }
Het gedrag van het programma tijdens runtime voor invoer 100:
Unhandled Exception: System.TypeLoadException: Could not load type 'Program' from assembly 'repro, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null'.
at Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowTypeLoadExceptionWithArgument(ExceptionStringID, String, String, String) + 0x42
at Program.<<Main>$>g__CauseGenericRecursion|0_0[T](Int32) + 0x29
at Program.<<Main>$>g__CauseGenericRecursion|0_0[T](Int32) + 0x1f
at Program.<<Main>$>g__CauseGenericRecursion|0_0[T](Int32) + 0x1f
at Program.<<Main>$>g__CauseGenericRecursion|0_0[T](Int32) + 0x1f
at Program.<<Main>$>g__CauseGenericRecursion|0_0[T](Int32) + 0x1f
at Program.<Main>$(String[]) + 0x3a
Op dezelfde manier veroorzaakt het volgende programma recursie binnen systeemeigen gegevensstructuren (in tegenstelling tot algemene recursie binnen systeemeigen code), omdat de instantiëring een verwijzingstype heeft, maar een cyclus heeft:
// AOT analysis warning IL3054:
// Program.<<Main>$>g__Recursive|0_0<List`1<List`1<List`1<List`1<Object>>>>>():
// Generic expansion to 'Program.<<Main>$>g__Recursive|0_0<List`1<List`1<List`1<List`1<List`1<Object>>>>>>()'
// was aborted due to generic recursion. An exception will be thrown at runtime if this codepath
// is ever reached. Generic recursion also negatively affects compilation speed and the size of
// the compilation output. It is advisable to remove the source of the generic recursion
// by restructuring the program around the source of recursion. The source of generic recursion
// might include: 'Program.<<Main>$>g__Recursive|0_0<T>()'
using System.Collections.Generic;
Recursive<object>();
static void Recursive<T>() => Recursive<List<T>>();