Delen via


Macro's in X++

Opmerking

Community-belangengroepen zijn nu verplaatst van Yammer naar Microsoft Viva Engage. Als u wilt deelnemen aan een Viva Engage-community en deel wilt nemen aan de meest recente discussies, vult u het formulier Toegang aanvragen tot Finance and Operations Viva Engage Community in en kiest u de community waaraan u wilt deelnemen.

In dit artikel wordt beschreven hoe u macro's maakt en gebruikt in X++.

Precompiler-instructies, dat wil gezegd macro's, worden conceptueel verwerkt voordat de code wordt gecompileerd. De instructies declareren en verwerken macro's en hun waarden. De instructies worden vervangen door de inhoud die ze aanwijzen, zodat de compiler deze nooit tegenkomt. De X++-compiler ziet alleen de reeks tekens die door de instructies in de X++-code zijn geschreven.

Waarschuwing

Macro's zijn verouderde functies en kunnen in toekomstige releases worden afgeschaft. Gebruik in plaats daarvan taalconstructies: Gebruik in plaats van macro's taalconstructies zoals deze:

Macro's definiëren

U definieert een benoemde macro met behulp van de onderstaande syntaxis

  • #define. Met MyMacro(Waarde) maakt u een macro met een optionele waarde.
  • #if. MyMacro controleert of een macro is gedefinieerd.
  • #undef. Met MyMacro wordt een macrodefinitie verwijderd.

richtlijnen voor #define en #if

Alle precompiler-instructies en symbolen beginnen met het # teken.

Definieer een macro met de volgende syntaxis:

#define.MyMacro(Value) // creates a macro with a value.
#define.AnotherMacro() // creates a macro without a value.

U kunt een macro overal in uw code definiëren. De macro kan een waarde hebben die een reeks tekens is, maar deze hoeft geen waarde te hebben. De #define instructie geeft de precompiler de opdracht om de macrovariabele te maken, eventueel inclusief een waarde.

De #if richtlijn controleert of de variabele is gedefinieerd en, optioneel, of deze een specifieke waarde heeft, zoals wordt weergegeven in het volgende voorbeeld:

#if.MyMacro
  // The MyNaacro is defined.
#endif

#ifnot.MyMacro
  // The MyNaacro is not defined.
#endif

De precompilerrichtlijnen voor X++ , de macronamen die ze definiëren en de #if instructiewaardetests zijn allemaal niet hoofdlettergevoelig. Definieer echter macronamen die beginnen met een hoofdletter.

#undef richtlijn

Gebruik de #undef instructie om een macrodefinitie te verwijderen die uit een vorige #definebestaat.

#undef.MyMacro
#if.MyMacro
   // The macro is not defined, so this is not included
#endif

U kunt een macronaam waarmee u hebt verwijderd #undef opnieuw definiëren met behulp van een andere #define.

Een macrowaarde gebruiken

U kunt een macronaam definiëren om een waarde te hebben.

#define.Offset(42)
...
print #Offset; // 42

Een macrowaarde heeft geen bepaald gegevenstype. Dit is slechts een reeks tekens. Wijs een waarde toe aan een macro door de waarde tussen haakjes aan het einde van een #define.MyMacro richtlijn op te geven. Gebruik het macrosymbool waar u de waarde in de X++-code wilt opnemen. Een macrosymbool is de naam van de macro met het # teken dat als voorvoegsel is toegevoegd. In het volgende codevoorbeeld ziet u een macrosymbool #MyMacro. Het symbool wordt vervangen door de waarde van de macro.

Een macrowaarde testen

U kunt een macro testen om te bepalen of deze een waarde heeft. U kunt ook bepalen of de waarde gelijk is aan een specifieke reeks tekens. Met deze tests kunt u regels code voorwaardelijk opnemen in uw X++-programma. Er is geen manier om te testen of een gedefinieerde macro een waarde heeft. U kunt alleen testen of de macrowaarde overeenkomt met een specifieke waarde. Als best practice definieert u altijd een waarde voor een macronaam die u definieert of definieert u nooit een waarde. Wanneer u tussen deze modi wisselt, wordt uw code moeilijk te begrijpen.

richtlijnen voor #defInc en #defDec

#defInc en #defDec zijn de enige instructies die de waarde van een macro interpreteren. Ze zijn alleen van toepassing op macro's met een waarde die de precompiler kan converteren naar het formele int-type . Deze instructies wijzigen de numerieke waarde van een macro tijdens het compileren. De waarde mag alleen getallen bevatten. Het enige niet-numerieke teken is een voorloop negatief teken (-). De geheel getalwaarde wordt behandeld als een X++- int, niet als een int64. Voor macronamen die door de #defInc richtlijn worden gebruikt, mag de #define instructie waarmee de macro wordt gemaakt, zich niet in een klassedeclaratie bevinden. Het gedrag van #defInc in deze gevallen is onvoorspelbaar. In plaats daarvan definieert u dergelijke macro's alleen in een methode. Gebruik de #defInc en #defDec instructies alleen voor macro's met een geheel getal. De precompiler volgt speciale regels voor #defInc wanneer de macrowaarde geen geheel getal is of wanneer de waarde ongebruikelijk of extreem is. De volgende tabel bevat de waarden die #defInc worden geconverteerd naar nul (0) en vervolgens oplopend. Wanneer #defInc een waarde wordt geconverteerd naar 0, kunt u de oorspronkelijke waarde niet herstellen, zelfs niet met behulp van #defDec.

Macrowaarde defInc-waarde Gedrag
(+55) 56 Met het voorvoegsel positiefteken (+) wordt deze waarde behandeld als een niet-numerieke tekenreeks. De precompiler behandelt alle niet-numerieke tekenreeksen als 0 wanneer een #defInc (of #defDec) instructie wordt verwerkt.
("3") 1 Gehele getallen tussen aanhalingstekens worden behandeld als 0.
( ) 1 Een tekenreeks met spaties wordt behandeld als 0.
() 1 Een tekenreeks met lengte nul wordt behandeld als 0.
(Willekeurige tekenreeks.) 1 Elke niet-numerieke tekenreeks wordt behandeld als 0.
(0x12) 1 Hexadecimale getallen worden behandeld als niet-numerieke tekenreeksen. Daarom converteert de precompiler deze naar 0.
(-44) -43 Negatieve getallen zijn acceptabel.
(2147483647) -2147483648 De maximale positieve int-waarde loopt over naar de minimum negatieve int-waarde door #defInc.
(999888777666555) 1 Een groot getal, buiten de capaciteit van int en int64.
(5.8) 1 Reële getallen worden geïnterpreteerd als 0.
1 Wanneer er geen waarde en geen haakjes voor de richtlijn #define.MyValuelessMacro worden opgegeven, is de waarde 0.

#globaldefine richtlijn

De #globaldefine richtlijn is vergelijkbaar met de #define richtlijn. Gebruik #define in plaats van #globaldefine.

richtlijnen voor #localmacro en #macro

De #localmacro instructie is een goede keuze wanneer u wilt dat een macro een waarde heeft die meerdere regels lang is, of wanneer uw macrowaarde een haakje sluiten bevat, zodat ze goede kandidaten zijn om broncodefragmenten te bevatten.

    #macro.RetailMatchedAggregatedSalesLine(
                %1.price            == %2.price
        &&      %1.businessDate     == %2.businessDate
        &&      %1.itemId           == %2.itemId
        &&      ((((%3) && (%1.qty <= 0)) || ((! %3) && (%1.qty > 0))) || (%4))
    )
    #endmacro

De #localmacro richtlijn kan worden geschreven als #macro. #localmacro Is echter de aanbevolen term. Met behulp van de #if instructie kunt u testen of een macronaam wordt gedeclareerd met de #define instructie. U kunt echter niet testen of de macronaam is gedeclareerd met de #localmacro instructie. Alleen macro's die door de #define richtlijn worden gedeclareerd, worden beïnvloed door de #undef richtlijn. In een #define richtlijn kunt u een naam opgeven die al binnen het bereik valt als een #localmacro. Het effect is om de #localmacro macro te verwijderen en te #define maken. Dit geldt ook voor de tegenovergestelde volgorde, wat betekent dat een herdefiniatie van een #localmacro#define. A #localmacro (met zowel een macronaam als een waarde) overschrijft altijd een vorige #localmacro met dezelfde naam. Ditzelfde probleem treedt op met #globaldefine. Het belangrijkste verschil tussen een #define macro en een #localmacro macro is de wijze waarop de syntaxis wordt beëindigd. De eindtekens zijn als volgt:

  • #define – wordt beëindigd door– )
  • #localmacro – wordt beëindigd door– #endmacro

#localmacro is een betere keuze voor macro's met meerdere lijnwaarden. Meerdere regelwaarden zijn doorgaans regels van X++ of SQL-code. X++ en SQL bevatten veel haakjes en deze zouden voortijdig een #define beëindigen. #define Beide #localmacro en kunnen worden gedeclareerd en beëindigd op één regel of op volgende regels. In de praktijk wordt de #define regel beëindigd op dezelfde regel waarop deze is gedeclareerd. In de praktijk wordt de #localmacro regel beëindigd op een volgende regel.

Macroparameters

U kunt macrowaarden definiëren om parametersymbolen op te nemen. Het eerste parametersymbool is %1, de tweede is %2, enzovoort. U geeft waarden door voor de parameters wanneer u verwijst naar de naam van het macrosymbool voor uitbreiding. Macroparameterwaarden zijn tekenreeksen van geen formeel type en ze worden door komma's gescheiden. Er is geen manier om een komma door te geven als onderdeel van een parameterwaarde. Het aantal doorgegeven parameters kan kleiner zijn dan, groter dan of gelijk aan het aantal parameters dat de macrowaarde is ontworpen om te ontvangen. Het systeem tolereert niet-overeenkomende waarden in het aantal doorgegeven parameters. Als er minder parameters worden doorgegeven dan de macro verwacht, wordt elke weggelaten parameter behandeld als een reeks tekens met lengte nul.

Macrosymbolen nesten

U kunt precompilerdefinitierichtlijnen nesten binnen een buitenste definitie-instructie. De belangrijkste definitierichtlijnen zijn #define en #localmacro.

Een #define richtlijn kan binnen een #localmacro richtlijn worden gegeven, en een #localmacro richtlijn kan binnen een #define.

#macrolib richtlijn

In de Toepassingsverkenner onder het knooppunt Macro's onder het codeknooppunt zijn er veel bibliotheekknooppunten die sets macro-instructies bevatten. Beide #define en #localmacro worden vaak weergegeven in de inhoud van deze macrobibliotheken. U kunt de #macrolib gebruiken. MyAOTMacroLibrary om de inhoud van een macrobibliotheek op te nemen in uw X++-code. De #if en #undef richtlijnen zijn niet van toepassing op #macrolib namen. Ze zijn echter van toepassing op #define instructies die de inhoud van een #macrolib macro zijn. De richtlijn #macrolib. MyAOTMacroLibrary kan ook worden geschreven als #MyAOTMacroLibrary. Het #macrolib voorvoegsel wordt aanbevolen omdat het nooit dubbelzinnig is voor een persoon die de code later leest.

#linenumber richtlijn

U kunt de #linenumber instructie gebruiken tijdens uw ontwikkeling en foutopsporing van code. Het wordt vervangen door het fysieke regelnummer in het codebestand vóór een macro-uitbreiding.

Macrobereik

Het bereik waarin u naar een macro kunt verwijzen, is afhankelijk van waar u de macro definieert. In een klasse kunt u verwijzen naar macro's die u in de bovenliggende klasse definieert. Wanneer de precompiler een onderliggende klasse afhandelt, wordt eerst de overnameketen aan de hoofdklasse gekoppeld. De precompiler verwerkt vervolgens alle instructies van de hoofdklasse naar de klasse die wordt gecompileerd. Alle macro's en de bijbehorende waarden worden opgeslagen in de interne tabellen. De resultaten van de richtlijnen in elke klassedeclaratie zijn van toepassing op de interne tabellen die al zijn ingevuld uit richtlijnen die eerder in de overnameketen zijn gevonden.

De precompiler verwerkt echter elke methode afzonderlijk. De interne tabellen worden bijgewerkt, zodat de status van de tabellen kan worden hersteld zoals ze waren voordat de huidige methode werd verwerkt. Nadat de precompiler de eerste methode heeft verwerkt, worden de interne tabellen hersteld voordat de volgende methode wordt verwerkt.

In deze context wordt een methode gedefinieerd als de inhoud van een methodeknooppunt in de AOT (Application Object Tree). In de AOT kunt u het knooppunt Klassen uitvouwen, een klasseknooppunt uitvouwen, met de rechtermuisknop op een methodeknooppunt klikken en vervolgens Bewerken selecteren. Vervolgens kunt u een regel voor de declaratie van #define.MyMacro("abc") de methode toevoegen. De precompiler behandelt deze #define richtlijn als onderdeel van de methode, ook al valt het #define buiten het {} blok van de methode.