Merk
Tilgang til denne siden krever autorisasjon. Du kan prøve å logge på eller endre kataloger.
Tilgang til denne siden krever autorisasjon. Du kan prøve å endre kataloger.
Note
Interessegrupper for fellesskapet har nå flyttet fra Yammer til Microsoft Viva Engage. Hvis du vil bli med i et Viva Engage-fellesskap og delta i de siste diskusjonene, fyller du ut skjemaet Be om tilgang til Finance and Operations Viva Engage Community og velger fellesskapet du vil bli med i.
Denne artikkelen beskriver hvordan du oppretter og bruker makroer i X++.
Precompiler-direktiver, det vil eksempelvis makroer, behandles konseptuelt før koden kompileres. Direktivene erklærer og håndterer makroer og deres verdier. Direktivene erstattes med innholdet de angir, slik at kompilatoren aldri møter dem. X++-kompilatoren ser bare sekvensen av tegn skrevet inn i X++-koden av direktivene.
Advarsel
Makroer er eldre funksjoner og kan bli avskrevet i fremtidige versjoner. Bruk språkkonstruksjoner i stedet: I stedet for makroer bruker du språkkonstruksjoner som disse:
- Konstanter
- Sysda for spørringer.
Definere makroer
Du definerer en navngitt makro ved hjelp av syntaksen som vises nedenfor
- #define. MyMacro(Value) oppretter en makro med en valgfri verdi.
- #if. MyMacro kontrollerer om en makro er definert.
- #undef. MyMacro fjerner en makrodefinisjon.
#define- og #if-direktiver
Alle precompiler-direktiver og symboler starter med # tegnet.
Definer en makro med følgende syntaks:
#define.MyMacro(Value) // creates a macro with a value.
#define.AnotherMacro() // creates a macro without a value.
Du kan definere en makro hvor som helst i koden. Makroen kan ha en verdi som er en sekvens med tegn, men den trenger ikke å ha en verdi. Direktivet #define ber precompileren om å opprette makrovariabelen, og eventuelt inkludere en verdi.
Direktivet #if kontrollerer om variabelen er definert, og eventuelt om den har en bestemt verdi, som vist i følgende eksempel:
#if.MyMacro
// The MyNaacro is defined.
#endif
#ifnot.MyMacro
// The MyNaacro is not defined.
#endif
X++-precompiler-direktivene, makronavnene de definerer, og direktivverditestene #if skiller ikke mellom store og små bokstaver. Definer imidlertid makronavn som starter med store bokstaver.
#undef-direktiv
Bruk direktivet #undef til å fjerne en makrodefinisjon som finnes fra en tidligere #define.
#undef.MyMacro
#if.MyMacro
// The macro is not defined, so this is not included
#endif
Du kan omdefinere et makronavn som du fjernet med #undef ved hjelp av et annet #define.
Bruke en makroverdi
Du kan definere et makronavn for å ha en verdi.
#define.Offset(42)
...
print #Offset; // 42
En makroverdi har ikke en bestemt datatype . Det er bare en sekvens med tegn. Tilordne en verdi til en makro ved å angi verdien i parenteser på slutten av et #define.MyMacro direktiv. Bruk makrosymbolet der du vil at verdien skal skje i X++-koden. Et makrosymbol er navnet på makroen med # tegnet lagt til som et prefiks. Følgende kodeeksempel viser et makrosymbol #MyMacro. Symbolet erstattes av verdien for makroen.
Test en makroverdi
Du kan teste en makro for å finne ut om den har en verdi. Du kan også bestemme om verdien er lik en bestemt tegnsekvens. Disse testene gjør det mulig for deg å inkludere kodelinjer i X++-programmet betinget. Det er ikke mulig å teste om en definert makro har en verdi. Du kan bare teste om makroverdien samsvarer med en bestemt verdi. Som en anbefalt fremgangsmåte definerer du alltid en verdi for et makronavn du definerer, eller aldri definerer en verdi. Når du veksler mellom disse modusene, blir koden vanskelig å forstå.
#defInc- og #defDec-direktiver
#defInc og #defDec er de eneste direktivene som tolker verdien for en makro. De gjelder bare for makroer som har en verdi som precompiler kan konvertere til den formelle heltallstypen . Disse direktivene endrer den numeriske verdien for en makro på kompileringstidspunktet. Verdien kan bare inneholde tall. Det eneste ikke-numeriske tegnet som er tillatt, er et innledende negativt tegn (-). Heltallsverdien behandles som et X++- heltall, ikke som et int64. For makronavn som direktivet #defInc bruker, bør ikke direktivet #define som oppretter makroen, ligge i en klassedeklarasjon. Oppførselen til #defInc i disse tilfellene er uforutsigbar. Definer i stedet slike makroer bare i en metode.
#defInc Bruk direktivene og #defDec bare for makroer som har en heltallsverdi. Precompiler følger spesielle regler for #defInc når makroverdien ikke er et heltall, eller når verdien er uvanlig eller ekstrem. Tabellen nedenfor viser verdiene som #defInc konverteres til null (0) og deretter intervaller. Når #defInc du konverterer en verdi til 0, kan du ikke gjenopprette den opprinnelige verdien, ikke engang ved hjelp #defDecav .
| Makroverdi | defInc-verdi | Virkemåte |
|---|---|---|
| (+55) | 56 | Prefikset for det positive tegnet (+) gjør at prekompileren behandler denne verdien som en ikke-numerisk streng. Precompiler behandler alle ikke-numeriske strenger som 0 når den håndterer et #defInc (eller #defDec) direktiv. |
| ("3") | 1 | Heltall i anførselstegn behandles som 0. |
| ( ) | 1 | En streng med mellomrom behandles som 0. |
| () | 1 | En tom streng behandles som 0. |
| (Tilfeldig streng.) | 1 | Alle ikke-numeriske tegnstrenger behandles som 0. |
| (0x12) | 1 | Heksadesimale tall behandles som ikke-numeriske strenger. Derfor konverterer precompiler dem til 0. |
| (-44) | -43 | Negative tall er akseptable. |
| (2147483647) | -2147483648 | Den maksimale positive int-verdien overflyter til minimum negativ heltallsverdi etter #defInc. |
| (999888777666555) | 1 | Et stort tall, utover kapasiteten til int og int64. |
| (5.8) | 1 | Reelle tall tolkes som 0. |
| 1 | Når ingen verdi og ingen parenteser er angitt for direktivet #define.MyValuelessMacro , er verdien 0. |
#globaldefine-direktiv
Direktivet #globaldefine ligner på direktivet #define . Bruk #define i stedet for #globaldefine.
#localmacro- og #macro-direktiver
Direktivet #localmacro er et godt valg når du vil at en makro skal ha en verdi som er flere linjer lang, eller når makroverdien inneholder en høyreparentes, noe som gjør dem til gode kandidater til å inneholde kildekodefragmenter.
#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 skrives som #macro. Er imidlertid #localmacro den anbefalte termen. Ved hjelp av direktivet #if kan du teste om et makronavn er deklarert med direktivet #define . Du kan imidlertid ikke teste om makronavnet er deklarert med direktivet #localmacro . Bare makroer deklarert ved hjelp av direktivet #define påvirkes av direktivet #undef . I et #define direktiv kan du angi et navn som allerede er i omfang som et #localmacro. Effekten er å forkaste #localmacro og opprette en #define makro. Dette gjelder også for den motsatte sekvensen, noe som betyr at en #localmacro kan omdefinere en #define. A #localmacro (som har både et makronavn og en verdi) overstyrer alltid en tidligere #localmacro som har samme navn. Det samme problemet oppstår med #globaldefine. Hovedforskjellen mellom en #define makro og en #localmacro makro er hvordan syntaksen avsluttes. Terminatorene er som følger:
-
#define– avsluttes av –) -
#localmacro– avsluttes av –#endmacro
#localmacro er et bedre valg for makroer med flere linjeverdier. Flere linjeverdier er vanligvis linjer med X++ eller SQL-kode. X++ og SQL inneholder mange parenteser, og disse vil for tidlig avslutte en #define. Begge #define deler og #localmacro kan deklareres og avsluttes enten på én enkelt linje eller på etterfølgende linjer. I praksis #define avsluttes den på samme linje som den deklareres på. I praksis avsluttes den #localmacro på en etterfølgende linje.
Makroparametere
Du kan definere makroverdier for å inkludere parametersymboler. Det første parametersymbolet er %1, det andre er %2og så videre. Du sender verdier for parameterne når du refererer til makrosymbolnavnet for utvidelse. Makroparameterverdier er tegnsekvenser uten formell type, og de er kommadelt. Det er ikke mulig å sende inn komma som en del av en parameterverdi. Antallet parametere som sendes, kan være mindre enn, større enn eller lik antall parametere som makroverdien er utformet for å motta. Systemet tolererer manglende samsvar i antall parametere som sendes. Hvis færre parametere sendes enn makroen forventer, behandles hver utelatte parameter som en nulllengdesekvens med tegn.
Neste makrosymboler
Du kan neste precompiler-definisjonsdirektiver i et ytre definisjonsdirektiv. Hoveddefinisjonsdirektivene er #define og #localmacro.
Et #define direktiv kan gis i et #localmacro direktiv, og en #localmacro kan være inne i et #define.
#macrolib-direktiv
I Programutforsker under Makroer-noden under kodenoden finnes det mange biblioteknoder som inneholder sett med makrodirektiver. Både #define og #localmacro vises ofte i innholdet i disse makrobibliotekene. Du kan bruke #macrolib. MyAOTMacroLibrary for å inkludere innholdet i et makrobibliotek i X++-koden.
#if Og #undef direktivene gjelder ikke for #macrolib navn. De gjelder imidlertid for #define direktiver som er innholdet i en #macrolib makro. Direktivet #macrolib. MyAOTMacroLibrary kan også skrives som #MyAOTMacroLibrary. Prefikset #macrolib anbefales fordi det aldri er tvetydig for en person som senere leser koden.
#linenumber-direktiv
Du kan bruke direktivet #linenumber under utvikling og feilsøking av kode. Den erstattes av det fysiske linjenummeret i kodefilen før en makroutvidelse.
Makroomfang
Området der du kan referere til en makro, avhenger av hvor du definerer makroen. I en klasse kan du referere til makroer som du definerer i den overordnede klassen. Når precompiler håndterer en underordnet klasse, sporer den først arvekjeden til rotklassen. Precompiler behandler deretter alle direktivene fra rotklassen til klassen som kompileres. Den lagrer alle makroene og verdiene i de interne tabellene. Resultatene av direktivene i hver klassedeklarasjon gjelder for de interne tabellene som allerede er fylt ut fra direktiver som den fant tidligere i arvekjeden.
Precompiler håndterer imidlertid hver metode separat. Den oppdaterer de interne tabellene slik at de kan gjenopprette tilstanden til tabellene slik de var før de behandlet den gjeldende metoden. Når precompiler håndterer den første metoden, gjenoppretter den de interne tabellene før du håndterer neste metode.
I denne konteksten defineres en metode som innholdet i en metodenode i Application Object Tree (AOT). I AOT kan du utvide Klasser-noden, utvide en klassenode, høyreklikke på en metodenode og deretter velge Rediger. Deretter kan du legge til en linje for #define.MyMacro("abc") før metodedeklarasjonen. Precompiler behandler dette #define direktivet som en del av metoden, selv om det #define forekommer utenfor {} metodens blokk.