Sdílet prostřednictvím


Makra v X++

Poznámka:

Skupiny zájmu komunity se teď přesunuly z Yammeru na Microsoft Viva Engage. Pokud se chcete připojit k komunitě Viva Engage a účastnit se nejnovějších diskuzí, vyplňte formulář Žádost o přístup k aplikaci Finance and Operations Viva Engage Community a zvolte komunitu, ke které se chcete připojit.

Tento článek popisuje, jak vytvářet a používat makra v jazyce X++.

Direktivy prekompileru, tj. makra, jsou koncepčně zpracovány před kompilací kódu. Direktivy deklarují a zpracovávají makra a jejich hodnoty. Direktivy jsou nahrazeny obsahem, který určují, takže se s nimi kompilátor nikdy nesetká. Kompilátor X++ vidí posloupnost znaků zapsaných do kódu X++ pouze direktivami.

Výstraha

Makra jsou starší verze funkcí a v budoucích verzích můžou být zastaralá. Místo maker používejte konstruktory jazyka: Místo maker použijte jazykové konstrukty, jako jsou tyto:

Definování maker

Pojmenované makro definujete pomocí syntaxe uvedené níže.

  • #define. MyMacro(Value) vytvoří makro s volitelnou hodnotou.
  • #if. MyMacro zkontroluje, jestli je definováno makro.
  • #undef. MyMacro odebere definici makra.

direktivy #define a #if

Všechny direktivy a symboly předkompileru začínají znakem # .

Definujte makro s následující syntaxí:

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

Makro můžete definovat kdekoli v kódu. Makro může mít hodnotu, která je posloupností znaků, ale nemusí mít hodnotu. Direktiva #define dává předkompiler pokyn k vytvoření proměnné makra, volitelně včetně hodnoty.

Direktiva #if zkontroluje, jestli je proměnná definovaná a volitelně zda má konkrétní hodnotu, jak je znázorněno v následujícím příkladu:

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

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

Direktivy prekompileru X++, názvy maker, které definují, a #if testy hodnot direktiv jsou nerozlišující velká a malá písmena. Definujte však názvy maker, které začínají velkým písmenem.

direktiva #undef

Pomocí direktivy #undef odeberte definici makra, která existuje z předchozího #define.

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

Název makra, se kterým jste odebrali #undef , můžete předefinovat pomocí jiného #define.

Použití hodnoty makra

Název makra můžete definovat tak, aby měl hodnotu.

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

Hodnota makra nemá konkrétní datový typ – je to jen posloupnost znaků. Přiřaďte hodnotu k makre tím, že zadáte hodnotu uzavřenou v závorkách na konci direktivy #define.MyMacro . Použijte symbol makra všude, kde má být hodnota v kódu X++. Symbol makra je název makra s znakem # přidaným jako předpona. Následující ukázka kódu ukazuje symbol makra #MyMacro. Symbol se nahradí hodnotou makra.

Testování hodnoty makra

Makro můžete otestovat a zjistit, jestli má hodnotu. Můžete také určit, jestli se jeho hodnota rovná určité sekvenci znaků. Tyto testy umožňují podmíněně zahrnout řádky kódu do programu X++. Neexistuje způsob, jak otestovat, jestli má definované makro hodnotu. Testovat můžete pouze to, jestli hodnota makra odpovídá určité hodnotě. Osvědčeným postupem je vždy definovat hodnotu pro libovolný název makra, který definujete, nebo nikdy nedefinujte hodnotu. Když se mezi těmito režimy střídáte, je obtížné porozumět kódu.

direktivy #defInc a #defDec

#defInc a #defDec jsou jedinými direktivy, které interpretují hodnotu makra. Platí pouze pro makra, která mají hodnotu, kterou může prekompiler převést na formální typ int . Tyto direktivy mění číselnou hodnotu makra v době kompilace. Hodnota může obsahovat pouze čísla. Jediným nečíselným znakem je počáteční záporné znaménko (-). Celočíselná hodnota se považuje za int X++, nikoli jako int64. Pro názvy maker, které #defInc direktiva používá, by direktiva #define , která vytváří makro, neměla být umístěna v deklaraci třídy. Chování #defInc v těchto případech je nepředvídatelné. Místo toho definujte taková makra pouze v metodě. Direktivy a #defInc direktivy #defDec používejte pouze pro makra, která mají celočíselnou hodnotu. Prekompiler se řídí zvláštními pravidly, #defInc pokud hodnota makra není celé číslo nebo když je hodnota neobvyklá nebo extrémní. Následující tabulka uvádí hodnoty, které #defInc se převedou na nulu (0) a pak se zvýší. Při #defInc převodu hodnoty na 0 nelze obnovit původní hodnotu, a to ani pomocí .#defDec

Hodnota makra defInc Value Chování
(+55) 56 Předpona kladného znaménka (+) způsobí, že prekompiler považuje tuto hodnotu za nečíselný řetězec. Precompiler zpracovává všechny nečíselné řetězce jako 0, když zpracovává direktivu #defInc (nebo #defDec).
("3") 1 Celá čísla uzavřená v uvozovkách jsou považována za 0.
( ) 1 Řetězec mezer se považuje za 0.
() 1 Řetězec nulové délky se považuje za 0.
(Náhodný řetězec.) 1 Jakýkoli nečíselný řetězec znaků je považován za 0.
(0x12) 1 Šestnáctková čísla se považují za nečíselné řetězce. Proto je prekompiler převede na 0.
(-44) -43 Záporná čísla jsou přijatelná.
(2147483647) -2147483648 Maximální kladná hodnota int přeteče na minimální zápornou hodnotu o #defInc.
(999888777666555) 1 Libovolný velký počet nad rámec kapacity int a int64.
(5.8) 1 Reálná čísla se interpretují jako 0.
1 Pokud nejsou pro direktivu #define.MyValuelessMacro zadána žádná hodnota a žádné závorky, hodnota je 0.

direktiva #globaldefine

Direktiva #globaldefine je podobná direktivě #define . Místo #definepoužijte #globaldefine .

direktivy #localmacro a #macro

Direktiva #localmacro je dobrou volbou, pokud chcete, aby makro obsahovalo hodnotu, která má délku několika řádků, nebo když hodnota makra obsahuje pravou závorku, takže je vhodné použít k tomu, aby obsahovala fragmenty zdrojového kódu.

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

Směrnice #localmacro může být napsána jako #macro. Doporučuje se však #localmacro termín. Pomocí direktivy #if můžete otestovat, zda je název makra deklarován s direktivou #define . Nemůžete ale otestovat, jestli je název makra deklarován direktivou #localmacro . Direktiva ovlivňuje pouze makra deklarovaná pomocí #define direktivy #undef . V direktivě #define můžete zadat název, který je již v oboru jako #localmacro. Výsledkem je zahodit #localmacro a vytvořit #define makro. To platí také pro opačnou sekvenci, což znamená, že #localmacro lze předefinovat #define. A #localmacro (který má název makra i hodnotu) vždy přepíše předchozí #localmacro název, který má stejný název. K tomuto problému dochází u #globaldefine. Hlavním rozdílem #define mezi makrem a #localmacro makrem je způsob ukončení jejich syntaxe. Ukončovací nástavce jsou následující:

  • #define – je ukončena )
  • #localmacro – je ukončena #endmacro

#localmacro je lepší volbou pro makra s více hodnotami řádků. Víceřádkové hodnoty jsou obvykle řádky kódu X++ nebo SQL. X++ a SQL obsahují velké množství závorek a ty by předčasně ukončily #define. Obě #define a #localmacro lze je deklarovat a ukončit buď na jednom řádku, nebo na dalších řádcích. V praxi #define se ukončí na stejném řádku, na který se deklaruje. V praxi #localmacro se ukončí na následujícím řádku.

Parametry makra

Hodnoty maker můžete definovat tak, aby zahrnovaly symboly parametrů. První symbol parametru je , druhý je %1%2a tak dále. Hodnoty parametrů předáte při odkazování na název symbolu makra pro rozšíření. Hodnoty parametrů makra jsou sekvence znaků bez formálního typu a jsou oddělené čárkami. Neexistuje způsob, jak předat čárku jako součást hodnoty parametru. Počet předaných parametrů může být menší než, větší nebo roven počtu parametrů, které má hodnota makra přijmout. Systém toleruje neshody v počtu předaných parametrů. Pokud se předá méně parametrů, než makro očekává, bude každý vynechaný parametr považován za posloupnost znaků s nulovou délkou.

Vnoření symbolů maker

Direktivy definice předkompileru můžete vnořit do vnější direktivy definice. Hlavní direktivy definice jsou #define a #localmacro.

Direktiva #define může být uvedena uvnitř #localmacro direktivy a #localmacro může být uvnitř #define.

direktiva #macrolib

V Průzkumníku aplikací pod uzlem Makra v uzlu Kód existuje mnoho uzlů knihovny, které obsahují sady direktiv maker. Obě #define knihovny maker se #localmacro často zobrazují v obsahu těchto knihoven maker. Můžete použít #macrolib. MyAOTMacroLibrary pro zahrnutí obsahu knihovny maker do kódu X++. #if Tyto #undef direktivy se nevztahují na #macrolib názvy. Vztahují se však na #define direktivy, které jsou obsahem #macrolib makra. Směrnice #macrolib. MyAOTMacroLibrary lze také psát jako #MyAOTMacroLibrary. Předpona #macrolib se doporučuje, protože není nikdy nejednoznačná pro osobu, která později kód přečte.

#linenumber – direktiva

Direktivu #linenumber můžete použít při vývoji a ladění kódu. Před rozšířením makra se nahradí fyzickým číslem řádku v souboru kódu.

Obor makra

Oblast, ve které můžete odkazovat na makro, závisí na tom, kde makro definujete. Ve třídě můžete odkazovat na makra, která definujete v nadřazené třídě. Když prekompiler zpracovává podřízenou třídu, nejprve trasuje řetězec dědičnosti do kořenové třídy. Prekompiler pak zpracuje všechny direktivy z kořenové třídy do zkompilované třídy. Uloží všechna makra a jejich hodnoty do interních tabulek. Výsledky direktiv v každé deklaraci třídy se vztahují na interní tabulky, které jsou již naplněny direktivy, které byly nalezeny dříve v řetězu dědičnosti.

Prekompiler ale zpracovává každou metodu samostatně. Aktualizuje své interní tabulky, aby mohl obnovit stav tabulek tak, jak byly před zpracováním aktuální metody. Jakmile prekompiler zpracuje první metodu, obnoví interní tabulky před zpracováním další metody.

V tomto kontextu je metoda definována jako obsah uzlu metody ve stromu objektů aplikace (AOT). V AOT můžete rozbalit uzel Třídy, rozbalit uzel třídy, kliknout pravým tlačítkem myši na uzel metody a pak vybrat Upravit. Potom můžete přidat řádek před #define.MyMacro("abc") deklaraci metody. Prekompiler považuje tuto #define direktivu za součást metody, i když #define dojde mimo {} blok metody.