Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of mappen te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen om mappen te wijzigen.
Wanneer u uw toepassing publiceert als systeemeigen AOT, produceert het buildproces alle systeemeigen code en gegevensstructuren die nodig zijn om de toepassing tijdens runtime te ondersteunen. Dit verschilt van niet-systeemeigen implementaties, die de toepassing uitvoeren op basis van indelingen die de toepassing in abstracte termen beschrijven (een programma voor een virtuele machine) en systeemeigen representaties op aanvraag maken tijdens runtime.
De abstracte representaties van programmaonderdelen hebben geen directe overeenkomst met de natuurlijke weergave. De abstracte beschrijving van de algemene List<T>.Add methode wordt bijvoorbeeld toegewezen aan mogelijk oneindige systeemeigen methode-lichamen die speciaal moeten zijn voor de gegeven T (bijvoorbeeld List<int>.Add en List<double>.Add).
Omdat de relatie van abstracte code naar systeemeigen code niet een-op-een is, moet het buildproces een volledige lijst maken met systeemeigen codeteksten en gegevensstructuren tijdens de build. Het kan lastig zijn om deze lijst tijdens de build te maken voor sommige .NET-API's. Als de API wordt gebruikt op een manier die niet werd verwacht tijdens de build, wordt er tijdens runtime een uitzondering gegenereerd.
Om te voorkomen dat wijzigingen in gedrag optreden bij het implementeren als systeemeigen AOT, biedt de .NET SDK statische analyse van AOT-compatibiliteit via 'AOT-waarschuwingen'. AOT-waarschuwingen worden geproduceerd wanneer de build code vindt die mogelijk niet compatibel is met AOT. Code die niet compatibel is met AOT, kan gedragswijzigingen veroorzaken of zelfs crashes in een toepassing veroorzaken nadat deze is gebouwd als systeemeigen AOT. In het ideale geval mogen alle toepassingen die gebruikmaken van Native AOT geen AOT-waarschuwingen hebben. Als er AOT-waarschuwingen zijn, moet u ervoor zorgen dat er geen gedragswijzigingen zijn door uw app grondig te testen na het bouwen als systeemeigen AOT.
Voorbeelden van AOT-waarschuwingen
Voor de meeste C#-code is het eenvoudig om te bepalen welke systeemeigen code moet worden gegenereerd. De systeemeigen compiler kan de methodeteksten doorlopen en vinden welke systeemeigen code en gegevensstructuren worden geopend. Helaas vormen sommige functies, zoals weerspiegeling, een belangrijk probleem. Houd rekening met de volgende code:
Type t = typeof(int);
while (true)
{
t = typeof(GenericType<>).MakeGenericType(t);
Console.WriteLine(Activator.CreateInstance(t));
}
struct GenericType<T> { }
Hoewel het bovenstaande programma niet erg nuttig is, is het een extreem geval waarvoor een oneindig aantal algemene typen moet worden gemaakt bij het bouwen van de toepassing als Systeemeigen AOT. Zonder systeemeigen AOT zou het programma worden uitgevoerd totdat het onvoldoende geheugen meer heeft. Met systeemeigen AOT zouden we het zelfs niet kunnen bouwen als we alle benodigde typen zouden genereren (het oneindige aantal).
In dit geval geeft de Native AOT-build de volgende waarschuwing op de MakeGenericType lijn:
AOT analysis warning IL3050: Program.<Main>$(String[]): Using member 'System.Type.MakeGenericType(Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.
Tijdens runtime genereert de toepassing inderdaad een uitzondering van de MakeGenericType aanroep.
Reageren op AOT-waarschuwingen
De AOT-waarschuwingen zijn bedoeld om voorspelbaarheid te bieden aan systeemeigen AOT-builds. Een meerderheid van de AOT-waarschuwingen gaat over mogelijke runtime-uitzonderingen in situaties waarin systeemeigen code niet is gegenereerd ter ondersteuning van het scenario. De breedste categorie is RequiresDynamicCodeAttribute.
RequiresDynamicCode
RequiresDynamicCodeAttribute is eenvoudig en breed: het is een kenmerk dat betekent dat het lid is geannoteerd als niet compatibel met AOT. Deze aantekening betekent dat het lid reflectie of een ander mechanisme kan gebruiken om tijdens runtime nieuwe systeemeigen code te maken. Dit kenmerk wordt gebruikt wanneer code fundamenteel niet compatibel is met AOT of de systeemeigen afhankelijkheid te complex is om statisch te voorspellen tijdens de build. Dit geldt vaak voor methoden die gebruikmaken van de Type.MakeGenericType API, reflectie-emit of andere technologieën voor het genereren van runtimecode. De volgende code laat een voorbeeld zien.
[RequiresDynamicCode("Use 'MethodFriendlyToAot' instead")]
void MethodWithReflectionEmit() { ... }
void TestMethod()
{
// IL3050: Using method 'MethodWithReflectionEmit' which has 'RequiresDynamicCodeAttribute'
// can break functionality when AOT compiling. Use 'MethodFriendlyToAot' instead.
MethodWithReflectionEmit();
}
Er zijn niet veel tijdelijke oplossingen voor RequiresDynamicCode. De beste oplossing is om te voorkomen dat de methode helemaal wordt aangeroepen bij het gebruik van Native AOT en iets anders te gebruiken dat compatibel is met AOT. Als u een bibliotheek schrijft en het niet onder uw controle is of de methode wordt aangeroepen, kunt u RequiresDynamicCode ook aan uw eigen methode toevoegen. Hiermee wordt uw methode gemarkeerd als niet AOT-compatibel. Door RequiresDynamicCode toe te voegen, worden alle AOT-waarschuwingen in de geannoteerde methode stilgelegd, maar het zal een waarschuwing genereren wanneer iemand anders deze aanroept. Daarom is het vooral nuttig voor ontwikkelaars van bibliotheken om de waarschuwing door te geven aan een openbare API.
Als u op een of andere manier kunt bepalen dat de aanroep veilig is en alle systeemeigen code tijdens runtime beschikbaar is, kunt u de waarschuwing ook onderdrukken met behulp van UnconditionalSuppressMessageAttribute. Voorbeeld:
[RequiresDynamicCode("Use 'MethodFriendlyToAot' instead")]
void MethodWithReflectionEmit() { ... }
[UnconditionalSuppressMessage("Aot", "IL3050:RequiresDynamicCode",
Justification = "The unfriendly method is not reachable with AOT")]
void TestMethod()
{
If (RuntimeFeature.IsDynamicCodeSupported)
MethodWithReflectionEmit(); // warning suppressed
}
UnconditionalSuppressMessage is zoals SuppressMessage, maar het kan worden gezien door publish en andere tools na de build.
SuppressMessage en #pragma instructies zijn alleen aanwezig in het broncodedocument, dus kunnen ze niet worden gebruikt om waarschuwingen van de build te onderdrukken.
Waarschuwing
Wees voorzichtig bij het onderdrukken van AOT-waarschuwingen. De aanroep is nu mogelijk compatibel met AOT, maar wanneer u uw code bijwerkt, kan dit veranderen en kunt u mogelijk vergeten alle uitzonderingen op te heffen.