Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Anmärkning
Intressegrupper för communityn har nu flyttat från Yammer till Microsoft Viva Engage. Om du vill gå med i en Viva Engage-community och delta i de senaste diskussionerna fyller du i formuläret Begär åtkomst till Finance and Operations Viva Engage Community och väljer den community som du vill ansluta till.
Den här artikeln beskriver hur du skapar och använder makron i X++.
Precompiler-direktiv, dvs. makron, bearbetas konceptuellt innan koden kompileras. Direktiven deklarerar och hanterar makron och deras värden. Direktiven ersätts med det innehåll som de anger, så kompilatorn stöter aldrig på dem. X++-kompilatorn ser bara sekvensen med tecken som skrivs till X++-koden av direktiven.
Varning
Makron är äldre funktioner och kan vara inaktuella i framtida versioner. Använd språkkonstruktioner i stället: I stället för makron använder du språkkonstruktioner som dessa:
- Konstanter
- Sysda för frågor.
Definiera makron
Du definierar ett namngivet makro med hjälp av syntaxen som visas nedan
- #define. MyMacro(Value) skapar ett makro med ett valfritt värde.
- #if. MyMacro kontrollerar om ett makro har definierats.
- #undef. MyMacro tar bort en makrodefinition.
#define och #if direktiv
Alla förkompilerare direktiv och symboler börjar med # tecknet.
Definiera ett makro med följande syntax:
#define.MyMacro(Value) // creates a macro with a value.
#define.AnotherMacro() // creates a macro without a value.
Du kan definiera ett makro var som helst i koden. Makrot kan ha ett värde som är en sekvens med tecken, men det behöver inte ha något värde. Direktivet #define instruerar förkompileraren att skapa makrovariabeln, eventuellt inklusive ett värde.
Direktivet #if kontrollerar om variabeln har definierats och eventuellt om den har ett specifikt värde, enligt följande exempel:
#if.MyMacro
// The MyNaacro is defined.
#endif
#ifnot.MyMacro
// The MyNaacro is not defined.
#endif
X++ precompiler-direktiven, makronamnen de definierar och #if direktivvärdetesterna är alla skiftlägeskänsliga. Definiera dock makronamn som börjar med en versal bokstav.
#undef direktiv
#undef Använd direktivet för att ta bort en makrodefinition som finns från en tidigare #define.
#undef.MyMacro
#if.MyMacro
// The macro is not defined, so this is not included
#endif
Du kan omdefiniera ett makronamn som du har tagit bort med #undef med hjälp av ett annat #define.
Använda ett makrovärde
Du kan definiera ett makronamn så att det har ett värde.
#define.Offset(42)
...
print #Offset; // 42
Ett makrovärde har ingen viss datatyp – det är bara en sekvens med tecken. Tilldela ett värde till ett makro genom att ange värdet inom parenteser i slutet av ett #define.MyMacro direktiv. Använd makrosymbolen var du vill att värdet ska ske i X++-koden. En makrosymbol är namnet på makrot med # tecknet som läggs till som prefix. Följande kodexempel visar en makrosymbol #MyMacro. Symbolen ersätts med makrots värde.
Testa ett makrovärde
Du kan testa ett makro för att avgöra om det har ett värde. Du kan också avgöra om dess värde är lika med en viss sekvens med tecken. Med de här testerna kan du villkorligt inkludera kodrader i X++-programmet. Det går inte att testa om ett definierat makro har ett värde. Du kan bara testa om makrovärdet matchar ett visst värde. Vi rekommenderar att du alltid definierar ett värde för alla makronamn som du definierar eller aldrig definierar ett värde. När du växlar mellan dessa lägen blir koden svår att förstå.
#defInc och #defDec direktiv
#defInc och #defDec är de enda direktiv som tolkar värdet för ett makro. De gäller endast makron som har ett värde som förkompileraren kan konvertera till den formella int-typen . Dessa direktiv ändrar det numeriska värdet för ett makro vid kompileringstillfället. Värdet får bara innehålla tal. Det enda icke-numeriska tecken som tillåts är ett inledande negativt tecken (-). Heltalsvärdet behandlas som en X++ -int, inte som en int64. För makronamn som #defInc direktivet använder #define ska det direktiv som skapar makrot inte finnas i en klassdeklaration. Beteendet #defInc för i dessa fall är oförutsägbart. Definiera i stället sådana makron i endast en metod. Använd endast direktiven #defInc och #defDec för makron som har ett heltalsvärde. Förkompileraren följer särskilda regler för #defInc när makrovärdet inte är ett heltal, eller när värdet är ovanligt eller extremt. I följande tabell visas de värden som #defInc konverteras till noll (0) och sedan ökar. När #defInc du konverterar ett värde till 0 kan du inte återställa det ursprungliga värdet, inte ens med hjälp #defDecav .
| Makrovärde | defInc-värde | Beteende |
|---|---|---|
| (+55) | 56 | Det positiva teckenprefixet (+) gör att precompiler behandlar det här värdet som en icke-numerisk sträng. Förkompileraren behandlar alla icke-numeriska strängar som 0 när den hanterar ett #defInc (eller #defDec) direktiv. |
| ("3") | 1 | Heltal omgivna inom citattecken behandlas som 0. |
| ( ) | 1 | En sträng med blanksteg behandlas som 0. |
| () | 1 | En sträng med noll längd behandlas som 0. |
| (Slumpmässig sträng.) | 1 | Alla icke-numeriska teckensträngar behandlas som 0. |
| (0x12) | 1 | Hexadecimala tal behandlas som icke-numeriska strängar. Därför konverterar precompiler dem till 0. |
| (-44) | -43 | Negativa tal är acceptabla. |
| (2147483647) | -2147483648 | Det maximala positiva int-värdet flödar över till det minsta negativa int-värdet med #defInc. |
| (999888777666555) | 1 | Ett stort antal, utöver kapaciteten för int och int64. |
| (5.8) | 1 | Verkliga tal tolkas som 0. |
| 1 | När inget värde och inga parenteser anges för direktivet #define.MyValuelessMacro är värdet 0. |
#globaldefine direktiv
Direktivet #globaldefine liknar #define direktivet. Använd #define i stället för #globaldefine.
#localmacro och #macro direktiv
Direktivet #localmacro är ett bra val när du vill att ett makro ska ha ett värde som är flera rader långt, eller när makrovärdet innehåller en avslutande parentes, vilket gör dem till bra kandidater för att innehålla källkodsfragment.
#macro.RetailMatchedAggregatedSalesLine(
%1.price == %2.price
&& %1.businessDate == %2.businessDate
&& %1.itemId == %2.itemId
&& ((((%3) && (%1.qty <= 0)) || ((! %3) && (%1.qty > 0))) || (%4))
)
#endmacro
Direktivet #localmacro kan skrivas som #macro. Är dock #localmacro den rekommenderade termen. Genom att #if använda direktivet kan du testa om ett makronamn deklareras med #define direktivet. Du kan dock inte testa om makronamnet har deklarerats med #localmacro direktivet. Endast makron som deklareras med hjälp #define av direktivet påverkas av #undef direktivet. I ett #define direktiv kan du ange ett namn som redan finns i omfånget som en #localmacro. Effekten är att ta bort #localmacro och skapa ett #define makro. Detta gäller även för den motsatta sekvensen, vilket innebär att en #localmacro kan omdefiniera en #define. A #localmacro (som har både ett makronamn och ett värde) åsidosätter alltid en tidigare #localmacro som har samma namn. Samma problem uppstår med #globaldefine. Den största skillnaden mellan ett #define makro och ett #localmacro makro är hur deras syntax avslutas. Avslutarna är följande:
-
#define– avslutas av–) -
#localmacro– avslutas av–#endmacro
#localmacro är ett bättre alternativ för makron med flera radvärden. Flera radvärden är vanligtvis rader med X++ eller SQL-kod. X++ och SQL innehåller många parenteser, och dessa skulle avsluta en #define i förtid. Både #define och #localmacro kan deklareras och avslutas på antingen en enda rad eller på efterföljande rader. I praktiken #define avslutas den på samma rad som den deklareras på. I praktiken avslutas den #localmacro på en efterföljande rad.
Makroparametrar
Du kan definiera makrovärden för att inkludera parametersymboler. Den första parametersymbolen är %1, den andra är %2, och så vidare. Du skickar värden för parametrarna när du refererar till makrosymbolnamnet för expansion. Makroparametervärden är teckensekvenser utan formell typ och de avgränsas med kommatecken. Det går inte att skicka ett kommatecken som en del av ett parametervärde. Antalet parametrar som skickas kan vara mindre än, större än eller lika med antalet parametrar som makrovärdet är utformat för att ta emot. Systemet tolererar felmatchningar i antalet parametrar som skickas. Om färre parametrar skickas än vad makrot förväntar sig behandlas varje utelämnad parameter som en teckensekvens med noll längd.
Kapslade makrosymboler
Du kan kapsla definitionsdirektiv för förkompiler i ett yttre definitionsdirektiv. Huvuddefinitionsdirektiven är #define och #localmacro.
Ett #define direktiv kan anges i ett #localmacro direktiv och ett #localmacro kan finnas i ett #define.
#macrolib direktiv
I Application Explorer under noden Makron under kodnoden finns det många biblioteksnoder som innehåller uppsättningar makrodirektiv. Både #define och #localmacro visas ofta i innehållet i dessa makrobibliotek. Du kan använda #macrolib. MyAOTMacroLibrary för att inkludera innehållet i ett makrobibliotek i X++-koden. Direktiven #if och #undef gäller inte för #macrolib namn. De gäller dock för #define direktiv som är innehållet i ett #macrolib makro. Direktivet #macrolib. MyAOTMacroLibrary kan också skrivas som #MyAOTMacroLibrary. Prefixet #macrolib rekommenderas eftersom det aldrig är tvetydigt för en person som senare läser koden.
#linenumber direktiv
Du kan använda #linenumber direktivet under din utveckling och felsökning av kod. Den ersätts av det fysiska radnumret i kodfilen innan makroexpansionen.
Makroomfång
Det intervall där du kan referera till ett makro beror på var du definierar makrot. I en klass kan du referera till makron som du definierar i den överordnade klassen. När förkompileraren hanterar en underordnad klass spårar den först arvskedjan till rotklassen. Precompiler bearbetar sedan alla direktiv från rotklassen till den klass som kompileras. Den lagrar alla makron och deras värden i sina interna tabeller. Resultatet av direktiven i varje klassdeklaration gäller för de interna tabeller som redan är ifyllda från direktiv som den hittade tidigare i arvskedjan.
Precompiler hanterar dock varje metod separat. Den uppdaterar sina interna tabeller så att den kan återställa tillståndet för tabellerna som de var innan den aktuella metoden bearbetas. När förkompileraren har hanterat den första metoden återställs de interna tabellerna innan nästa metod hanteras.
I det här sammanhanget definieras en metod som innehållet i en metodnod i programobjektträdet (AOT). I AOT kan du expandera noden Klasser, expandera en klassnod, högerklicka på en metodnod och sedan välja Redigera. Sedan kan du lägga till en rad för #define.MyMacro("abc") före metoddeklarationen. Förkompileraren behandlar detta #define direktiv som en del av metoden, även om det #define sker utanför {} metodens block.