Skip to content

Chapter 1.12: What Does NOT Exist (Gotchas)

Home | << Previous: Error Handling | Gotchas | Next: Functions & Methods >>


Indice dei Contenuti


Riferimento Completo delle Insidie

1. No Ternary Operator

Cosa scriveresti:

c
int x = (condition) ? valueA : valueB;

Cosa succede: Errore di compilazione. The ? : operator does not exist.

Soluzione corretta:

c
int x;
if (condition)
    x = valueA;
else
    x = valueB;

2. No do...while Loop

Cosa scriveresti:

c
do {
    Process();
} while (HasMore());

Cosa succede: Errore di compilazione. The do keyword does not exist.

Soluzione corretta — flag pattern:

c
bool first = true;
while (first || HasMore())
{
    first = false;
    Process();
}

Soluzione corretta — break pattern:

c
while (true)
{
    Process();
    if (!HasMore())
        break;
}

3. No try/catch/throw

Cosa scriveresti:

c
try {
    RiskyOperation();
} catch (Exception e) {
    HandleError(e);
}

Cosa succede: Errore di compilazione. These keywords do not exist.

Soluzione corretta: Guard clauses with ritorno anticipato.

c
void DoOperation()
{
    if (!CanDoOperation())
    {
        ErrorEx("Cannot perform operation", ErrorExSeverity.WARNING);
        return;
    }

    // Proceed safely
    RiskyOperation();
}

Vedi Chapter 1.11 — Error Handling for full patterns.


4. No Multiple Inheritance

Cosa scriveresti:

c
class MyClass extends BaseA, BaseB  // Two base classes

Cosa succede: Errore di compilazione. Only ereditarieta' singola is supported.

Soluzione corretta: Inherit from one class, compose the other:

c
class MyClass extends BaseA
{
    ref BaseB m_Helper;

    void MyClass()
    {
        m_Helper = new BaseB();
    }
}

5. No Operator Overloading (Except Index)

Cosa scriveresti:

c
Vector3 operator+(Vector3 a, Vector3 b) { ... }
bool operator==(MyClass other) { ... }

Cosa succede: Errore di compilazione. Custom operators cannot be defined.

Soluzione corretta: Use named methods:

c
class MyVector
{
    float x, y, z;

    MyVector Add(MyVector other)
    {
        MyVector result = new MyVector();
        result.x = x + other.x;
        result.y = y + other.y;
        result.z = z + other.z;
        return result;
    }

    bool Equals(MyVector other)
    {
        return (x == other.x && y == other.y && z == other.z);
    }
}

Eccezione: The index operator [] can be overloaded via Get(index) and Set(index, value) methods:

c
class MyContainer
{
    int data[10];

    int Get(int index) { return data[index]; }
    void Set(int index, int value) { data[index] = value; }
}

MyContainer c = new MyContainer();
c[3] = 42;        // Calls Set(3, 42)
int v = c[3];     // Calls Get(3)

6. No Lambdas / Anonymous Functions

Cosa scriveresti:

c
array.Sort((a, b) => a.name.CompareTo(b.name));
button.OnClick += () => { DoSomething(); };

Cosa succede: Errore di compilazione. Lambda syntax does not exist.

Soluzione corretta: Define named methods and pass them as ScriptCaller or use string-based callbacks:

c
// Named method
void OnButtonClick()
{
    DoSomething();
}

// String-based callback (used by CallLater, timers, etc.)
GetGame().GetCallQueue(CALL_CATEGORY_GAMEPLAY).CallLater(this.OnButtonClick, 1000, false);

7. No Delegates / Function Pointers (Native)

Cosa scriveresti:

c
delegate void MyCallback(int value);
MyCallback cb = SomeFunction;
cb(42);

Cosa succede: Errore di compilazione. The delegate keyword does not exist.

Soluzione corretta: Use ScriptCaller, ScriptInvoker, or string-based method names:

c
// ScriptCaller (single callback)
ScriptCaller caller = ScriptCaller.Create(MyFunction);

// ScriptInvoker (event with multiple subscribers)
ref ScriptInvoker m_OnEvent = new ScriptInvoker();
m_OnEvent.Insert(MyHandler);
m_OnEvent.Invoke();  // Calls all registered handlers

8. No String Escape for Backslash/Quote

Cosa scriveresti:

c
string path = "C:\\Users\\folder";
string quote = "He said \"hello\"";

Cosa succede: CParser crashes or produces garbled output. The \\ and \" escape sequences break the string parser.

Soluzione corretta: Evita backslash and quote characters in string literals entirely:

c
// Use forward slashes for paths
string path = "C:/Users/folder";

// Use single quotes or rephrase to avoid embedded double quotes
string quote = "He said 'hello'";

// Use string concatenation if you absolutely need special chars
// (still risky — test thoroughly)

Nota: \n, \r, and \t escape sequences DO work. Only \\ and \" are broken.


9. No Variable Redeclaration in else-if Blocks

Cosa scriveresti:

c
if (condA)
{
    string msg = "Case A";
    Print(msg);
}
else if (condB)
{
    string msg = "Case B";  // Same variable name in sibling block
    Print(msg);
}

Cosa succede: Errore di compilazione: "multiple declaration of variable 'msg'". Enforce Script treats variables in sibling if/else if/else blocks as sharing the same scope.

Soluzione corretta — unique names:

c
if (condA)
{
    string msgA = "Case A";
    Print(msgA);
}
else if (condB)
{
    string msgB = "Case B";
    Print(msgB);
}

Soluzione corretta — declare before the if:

c
string msg;
if (condA)
{
    msg = "Case A";
}
else if (condB)
{
    msg = "Case B";
}
Print(msg);

10. No Ternary in Variable Declaration

Related to gotcha #1, but specific to declarations:

Cosa scriveresti:

c
string label = isAdmin ? "Admin" : "Player";

Soluzione corretta:

c
string label;
if (isAdmin)
    label = "Admin";
else
    label = "Player";

11. Object.IsAlive() Does NOT Exist on Base Object

Cosa scriveresti:

c
Object obj = GetSomething();
if (obj.IsAlive())  // Check if alive

Cosa succede: Errore di compilazione or crash a runtime. IsAlive() is defined on EntityAI, not on Object.

Soluzione corretta:

c
Object obj = GetSomething();
EntityAI eai;
if (Class.CastTo(eai, obj) && eai.IsAlive())
{
    // Safely alive
}

12. No nullptr — Use NULL or null

Cosa scriveresti:

c
if (obj == nullptr)

Cosa succede: Errore di compilazione. The nullptr keyword does not exist.

Soluzione corretta:

c
if (obj == null)    // lowercase works
if (obj == NULL)    // uppercase also works
if (!obj)           // idiomatic null check (preferred)

13. switch/case Does NOT Fall Through

Cosa scriveresti (expecting C/C++ fall-through):

c
switch (value)
{
    case 1:
    case 2:
    case 3:
        Print("1, 2, or 3");  // In C++, cases 1 and 2 fall through to here
        break;
}

Cosa succede: Only case 3 executes the Print. Cases 1 and 2 are empty — they do nothing and do NOT fall through.

Soluzione corretta:

c
if (value >= 1 && value <= 3)
{
    Print("1, 2, or 3");
}

// Or handle each case explicitly:
switch (value)
{
    case 1:
        Print("1, 2, or 3");
        break;
    case 2:
        Print("1, 2, or 3");
        break;
    case 3:
        Print("1, 2, or 3");
        break;
}

Nota: break is technically opzionale in Enforce Script since there is no fall-through, but it is conventional to include it.


14. No Predefinito Parameter Expressions

Cosa scriveresti:

c
void Spawn(vector pos = GetDefaultPos())    // Expression as default
void Spawn(vector pos = Vector(0, 100, 0))  // Constructor as default

Cosa succede: Errore di compilazione. Predefinito parameter values must be literals or NULL.

Soluzione corretta:

c
void Spawn(vector pos = "0 100 0")    // String literal for vector — OK
void Spawn(int count = 5)             // Integer literal — OK
void Spawn(float radius = 10.0)      // Float literal — OK
void Spawn(string name = "default")   // String literal — OK
void Spawn(Object obj = NULL)         // NULL — OK

// For complex defaults, use overloads:
void Spawn()
{
    Spawn(GetDefaultPos());  // Call the parametric version
}

void Spawn(vector pos)
{
    // Actual implementation
}

15. JsonFileLoader.JsonLoadFile Restituisce void

Cosa scriveresti:

c
MyConfig cfg = JsonFileLoader<MyConfig>.JsonLoadFile(path);
// or:
if (JsonFileLoader<MyConfig>.JsonLoadFile(path, cfg))

Cosa succede: Errore di compilazione. JsonLoadFile returns void, not the loaded object or a bool.

Soluzione corretta:

c
MyConfig cfg = new MyConfig();  // Create instance first with defaults
JsonFileLoader<MyConfig>.JsonLoadFile(path, cfg);  // Populates cfg in-place
// cfg now contains loaded values (or still has defaults if file was invalid)

Nota: The newer JsonFileLoader<T>.LoadFile() method returns bool, but JsonLoadFile (the commonly seen version) does not.


16. No #define Value Substitution

Cosa scriveresti:

c
#define MAX_PLAYERS 60
#define VERSION_STRING "1.0.0"
int max = MAX_PLAYERS;

Cosa succede: Errore di compilazione. Enforce Script #define only creates existence flags for #ifdef checks. It does not support value substitution.

Soluzione corretta:

c
// Use const for values
const int MAX_PLAYERS = 60;
const string VERSION_STRING = "1.0.0";

// Use #define only for conditional compilation flags
#define MY_MOD_ENABLED

17. No Interfaces / Abstract Classes (Enforced)

Cosa scriveresti:

c
interface ISerializable
{
    void Serialize();
    void Deserialize();
}

abstract class BaseProcessor
{
    abstract void Process();
}

Cosa succede: The interface and abstract keywords do not exist.

Soluzione corretta: Use regular classes with empty base methods:

c
// "Interface" — base class with empty methods
class ISerializable
{
    void Serialize() {}     // Override in subclass
    void Deserialize() {}   // Override in subclass
}

// "Abstract" class — same pattern
class BaseProcessor
{
    void Process()
    {
        ErrorEx("BaseProcessor.Process() must be overridden!", ErrorExSeverity.ERROR);
    }
}

class ConcreteProcessor extends BaseProcessor
{
    override void Process()
    {
        // Actual implementation
    }
}

The compiler does NOT enforce that subclasses override the base methods. Forgetting to override silently uses the empty base implementation.


18. No Generics Constraints

Cosa scriveresti:

c
class Container<T> where T : EntityAI  // Constrain T to EntityAI

Cosa succede: Errore di compilazione. The where clause does not exist. Template parameters accept any type.

Soluzione corretta: Validate at runtime:

c
class EntityContainer<Class T>
{
    void Add(T item)
    {
        // Runtime type check instead of compile-time constraint
        EntityAI eai;
        if (!Class.CastTo(eai, item))
        {
            ErrorEx("EntityContainer only accepts EntityAI subclasses");
            return;
        }
        // proceed
    }
}

19. No Enum Validation

Cosa scriveresti:

c
EDamageState state = (EDamageState)999;  // Expect error or exception

Cosa succede: No error. Any int value can be assigned to an enum variable, even values outside the defined range.

Soluzione corretta: Validate manually:

c
bool IsValidDamageState(int value)
{
    return (value >= EDamageState.PRISTINE && value <= EDamageState.RUINED);
}

int rawValue = LoadFromConfig();
if (IsValidDamageState(rawValue))
{
    EDamageState state = rawValue;
}
else
{
    Print("Invalid damage state: " + rawValue.ToString());
    EDamageState state = EDamageState.PRISTINE;  // fallback
}

20. No Variadic Parameters

Cosa scriveresti:

c
void Log(string format, params object[] args)
void Printf(string fmt, ...)

Cosa succede: Errore di compilazione. Variadic parameters do not exist.

Soluzione corretta: Use string.Format with fixed parameter counts, or use Param classes:

c
// string.Format supports up to 9 positional arguments
string msg = string.Format("Player %1 at %2 with %3 HP", name, pos, hp);

// For variable-count data, pass an array
void LogMultiple(string tag, array<string> messages)
{
    foreach (string msg : messages)
    {
        Print("[" + tag + "] " + msg);
    }
}

21. No Nested Class Declarations

Cosa scriveresti:

c
class Outer
{
    class Inner  // Nested class
    {
        int value;
    }
}

Cosa succede: Errore di compilazione. Classes cannot be declared inside other classes.

Soluzione corretta: Declare all classes at the top level, use naming conventions to show relationships:

c
class MySystem_Config
{
    int value;
}

class MySystem
{
    ref MySystem_Config m_Config;
}

22. Static Arrays Are Fixed-Size

Cosa scriveresti:

c
int size = GetCount();
int arr[size];  // Dynamic size at runtime

Cosa succede: Errore di compilazione. Static array sizes must be compile-time constants.

Soluzione corretta:

c
// Use a const for static arrays
const int BUFFER_SIZE = 64;
int arr[BUFFER_SIZE];

// Or use dynamic arrays for runtime sizing
array<int> arr = new array<int>;
arr.Resize(GetCount());

23. array.Remove Is Unordered

Cosa scriveresti (expecting order preservation):

c
array<string> items = {"A", "B", "C", "D"};
items.Remove(1);  // Expect: {"A", "C", "D"}

Cosa succede: Remove(index) swaps the element with the last element, then removes the last. Result: {"A", "D", "C"}. Order is NOT preserved.

Soluzione corretta:

c
// Use RemoveOrdered for order preservation (slower — shifts elements)
items.RemoveOrdered(1);  // {"A", "C", "D"} — correct order

// Use RemoveItem to find and remove by value (also ordered)
items.RemoveItem("B");   // {"A", "C", "D"}

24. No #include — Everything via config.cpp

Cosa scriveresti:

c
#include "MyHelper.c"
#include "Utils/StringUtils.c"

Cosa succede: No effect or errore di compilazione. Non c'e' #include directive.

Soluzione corretta: All script files are loaded through config.cpp in the mod's CfgMods entry. File loading order is determined by the script layer (3_Game, 4_World, 5_Mission) and alphabetical order within each layer.

cpp
// config.cpp
class CfgMods
{
    class MyMod
    {
        type = "mod";
        dependencies[] = { "Game", "World", "Mission" };

        class defs
        {
            class gameScriptModule
            {
                files[] = { "MyMod/Scripts/3_Game" };
            };
            class worldScriptModule
            {
                files[] = { "MyMod/Scripts/4_World" };
            };
            class missionScriptModule
            {
                files[] = { "MyMod/Scripts/5_Mission" };
            };
        };
    };
};

25. No Namespaces

Cosa scriveresti:

c
namespace MyMod { class Config { } }
namespace MyMod.Utils { class StringHelper { } }

Cosa succede: Errore di compilazione. The namespace keyword does not exist. All classes share a single global scope.

Soluzione corretta: Use naming prefixes to evita conflicts:

c
class MyConfig { }          // MyFramework
class MyAI_Config { }       // MyAI Mod
class MyM_MissionData { }   // MyMissions Mod
class VPP_AdminConfig { }     // VPP Admin

26. String Methods Modify In-Place

Cosa scriveresti (expecting a return value):

c
string upper = myString.ToUpper();  // Expect: returns new string

Cosa succede: ToUpper() and ToLower() modify the string in place and return void.

Soluzione corretta:

c
// Make a copy first if you need the original preserved
string original = "Hello World";
string upper = original;
upper.ToUpper();  // upper is now "HELLO WORLD", original unchanged

// Same for TrimInPlace
string trimmed = "  hello  ";
trimmed.TrimInPlace();  // "hello"

27. ref Cycles Cause Memory Leaks

Cosa scriveresti:

c
class Parent
{
    ref Child m_Child;
}
class Child
{
    ref Parent m_Parent;  // Circular ref — both ref each other
}

Cosa succede: Neither object is ever garbage collected. The reference counts never reach zero perche' each holds a ref to the other.

Soluzione corretta: One side must use a raw (non-ref) pointer:

c
class Parent
{
    ref Child m_Child;  // Parent OWNS the child (ref)
}
class Child
{
    Parent m_Parent;    // Child REFERENCES the parent (raw — no ref)
}

28. No Destructor Guarantee on Server Shutdown

Cosa scriveresti (expecting cleanup):

c
void ~MyManager()
{
    SaveData();  // Expect this runs on shutdown
}

Cosa succede: Server shutdown may kill the process before destructors run. Your save never happens.

Soluzione corretta: Save proactively at regular intervals and on known lifecycle events:

c
class MyManager
{
    void OnMissionFinish()  // Called before shutdown
    {
        SaveData();  // Reliable save point
    }

    void OnUpdate(float dt)
    {
        m_SaveTimer += dt;
        if (m_SaveTimer > 300.0)  // Every 5 minutes
        {
            SaveData();
            m_SaveTimer = 0;
        }
    }
}

29. No Scope-Based Resource Management (RAII)

Cosa scriveresti (in C++):

c
{
    FileHandle f = OpenFile("test.txt", FileMode.WRITE);
    // f automatically closed when scope ends
}

Cosa succede: Enforce Script does not close file handles when variables go out of scope (even with autoptr).

Soluzione corretta: Sempre close resources explicitly:

c
FileHandle fh = OpenFile("$profile:MyMod/data.txt", FileMode.WRITE);
if (fh != 0)
{
    FPrintln(fh, "data");
    CloseFile(fh);  // Must close manually!
}

30. GetGame().GetPlayer() Restituisce null on Server

Cosa scriveresti:

c
PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
player.DoSomething();  // CRASH on server!

Cosa succede: GetGame().GetPlayer() returns the local player. On a server dedicato, there is no local player — it returns null.

Soluzione corretta: On server, iterate the player list:

c
#ifdef SERVER
    array<Man> players = new array<Man>;
    GetGame().GetPlayers(players);
    foreach (Man man : players)
    {
        PlayerBase player;
        if (Class.CastTo(player, man))
        {
            player.DoSomething();
        }
    }
#else
    PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
    if (player)
    {
        player.DoSomething();
    }
#endif

31. Le classi sealed non possono essere estese (1.28+)

A partire da DayZ 1.28, il compilatore Enforce Script applica la parola chiave sealed. Una classe o un metodo contrassegnato sealed non puo essere ereditato o sovrascritto. Se provi a estendere una classe sealed:

c
// Se BI segna SomeVanillaClass come sealed:
class MyClass : SomeVanillaClass  // ERRORE DI COMPILAZIONE in 1.28+
{
}

Controlla il dump degli script vanilla per verificare se una classe e contrassegnata sealed prima di provare a ereditare da essa. Se devi modificare il comportamento di una classe sealed, usa la composizione (incapsulala come membro) invece dell'ereditarieta.


32. Limite parametri metodo: massimo 16 (1.28+)

Enforce Script ha sempre avuto un limite di 16 parametri per i metodi, ma prima della 1.28 era un overflow silenzioso del buffer che causava crash casuali. A partire dalla 1.28, il compilatore produce un errore hard:

c
// ERRORE DI COMPILAZIONE in 1.28+ — supera 16 parametri
void MyMethod(int a, int b, int c, int d, int e, int f, int g, int h,
              int i, int j, int k, int l, int m, int n, int o, int p,
              int q)  // 17esimo parametro = errore
{
}

Soluzione: Rifattorizza passando una classe o un array invece di parametri individuali.


33. Avvisi attributo Obsolete (1.28+)

DayZ 1.28 ha introdotto l'attributo Obsolete. Le funzioni e le classi contrassegnate con [Obsolete] generano avvisi del compilatore. Queste API funzionano ancora ma sono programmate per la rimozione in un futuro aggiornamento. Controlla l'output della build per gli avvisi di obsolescenza e migra all'alternativa raccomandata.


34. Bug di confronto int.MIN

I confronti che coinvolgono int.MIN (-2147483648) producono risultati errati:

c
int val = 1;
if (val < int.MIN)  // Si valuta come TRUE — dovrebbe essere false
{
    // Questo blocco viene eseguito in modo errato
}

Evita confronti diretti con int.MIN. Usa una costante memorizzata oppure confronta con un valore negativo specifico.


35. La negazione booleana di elementi array fallisce

La negazione booleana diretta degli elementi di un array non compila:

c
array<int> list = {0, 1, 2};
if (!list[1])          // NON COMPILA
if (list[1] == 0)      // Funziona — usa un confronto esplicito

Usa sempre controlli di uguaglianza espliciti quando verifichi gli elementi di un array per vero/falso.


36. Espressione complessa in assegnazione array causa crash

Assegnare un'espressione complessa direttamente a un elemento di un array puo causare un segmentation fault:

c
// CRASH a runtime
m_Values[index] = vector.DistanceSq(posA, posB) <= distSq;

// SICURO — usa una variabile intermedia
bool result = vector.DistanceSq(posA, posB) <= distSq;
m_Values[index] = result;

Memorizza sempre i risultati delle espressioni complesse in una variabile locale prima di assegnare a un array.


37. foreach su valore di ritorno del metodo causa crash

Usare foreach direttamente sul valore di ritorno di un metodo causa un'eccezione null pointer alla seconda iterazione:

c
// CRASH al 2o elemento
foreach (string item : GetMyArray())
{
}

// SICURO — memorizza prima in una variabile locale
array<string> items = GetMyArray();
foreach (string item : items)
{
}

38. Precedenza operatori bitwise vs confronto

Gli operatori bitwise hanno precedenza inferiore rispetto agli operatori di confronto, seguendo le regole C/C++:

c
int flags = 5;
int mask = 4;
if (flags & mask == mask)      // SBAGLIATO: valutato come flags & (mask == mask)
if ((flags & mask) == mask)    // CORRETTO: usa sempre le parentesi

39. Blocchi #ifdef / #ifndef vuoti causano crash

I blocchi condizionali del preprocessore vuoti — anche quelli contenenti solo commenti — causano segmentation fault:

c
#ifdef SOME_DEFINE
    // Questo blocco con solo commenti causa un SEGFAULT
#endif

Includi sempre almeno un'istruzione eseguibile o rimuovi completamente il blocco.


40. GetGame().IsClient() restituisce False durante il caricamento

Durante la fase di caricamento del client, GetGame().IsClient() restituisce false e GetGame().IsServer() restituisce true — anche sui client. Usa IsDedicatedServer() al suo posto:

c
// INAFFIDABILE durante la fase di caricamento
if (GetGame().IsClient()) { }   // false durante il caricamento!
if (GetGame().IsServer()) { }   // true durante il caricamento, anche sul client!

// AFFIDABILE
if (!GetGame().IsDedicatedServer()) { /* codice client */ }
if (GetGame().IsDedicatedServer())  { /* codice server */ }

Eccezione: Se devi supportare la modalita offline/giocatore singolo, IsDedicatedServer() restituisce false anche per i listen server.


41. I messaggi di errore di compilazione indicano il file sbagliato

Quando il compilatore incontra una classe non definita o un conflitto di nomi di variabili, segnala l'errore alla posizione EOF dell'ultimo file analizzato con successo — non alla posizione reale dell'errore. Se vedi un errore che punta a un file che non hai modificato, l'errore reale si trova nel file che veniva analizzato subito dopo.


42. I file crash_*.log non sono crash reali

I file di log chiamati crash_<data>_<ora>.log contengono eccezioni di runtime, non veri segmentation fault. Il nome e fuorviante — sono errori di script, non crash del motore.


Provenendo da C++

Se are a C++ developer, here are the biggest adjustments:

C++ Funzionalita'Enforce Script Equivalent
std::vectorarray<T>
std::mapmap<K,V>
std::unique_ptrref / autoptr
dynamic_cast<T*>Class.CastTo() or T.Cast()
try/catchGuard clauses
operator+Named methods (Add())
namespaceName prefixes (My, VPP_)
#includeconfig.cpp files[]
RAIIManual cleanup in lifecycle methods
Multiple inheritanceSingle inheritance + composition
nullptrnull / NULL
Templates with constraintsTemplates without constraints + runtime checks
do...whilewhile (true) { ... if (!cond) break; }

Provenendo da C#

C# Funzionalita'Enforce Script Equivalent
interfaceBase class with empty methods
abstractBase class + ErrorEx in base methods
delegate / eventScriptInvoker
Lambda =>Named methods
?. null conditionalManual null checks
?? null coalescingif (!x) x = default;
try/catchGuard clauses
using (IDisposable)Manual cleanup
Properties { get; set; }Public fields or explicit getter/setter methods
LINQManual loops
nameof()Hardcoded strings
async/awaitCallLater / timers

Provenendo da Java

Java Funzionalita'Enforce Script Equivalent
interfaceBase class with empty methods
try/catch/finallyGuard clauses
Garbage collectionref + reference counting (no GC for cycles)
@Overrideoverride keyword
instanceofobj.IsInherited(typename)
packageName prefixes
importconfig.cpp files[]
enum with methodsenum (int-only) + helper class
finalconst (for variables only)
AnnotationsNot available

Provenendo da Python

Python Funzionalita'Enforce Script Equivalent
Dynamic typingStatic typing (all variables typed)
try/exceptGuard clauses
lambdaNamed methods
List comprehensionManual loops
**kwargs / *argsFixed parameters
Duck typingIsInherited() / Class.CastTo()
__init__Constructor (same name as class)
__del__Destructor (~ClassName())
importconfig.cpp files[]
Multiple inheritanceSingle inheritance + composition
Nonenull / NULL
Indentation-based blocks{ } braces
f-stringsstring.Format("text %1 %2", a, b)

Tabella di Riferimento Rapido

Funzionalita'Exists?Soluzione alternativa
Ternary ? :Noif/else
do...whileNowhile + break
try/catchNoGuard clauses
Multiple inheritanceNoComposition
Operator overloadingIndex onlyNamed methods
LambdasNoNamed methods
DelegatesNoScriptInvoker
\\ / \" in stringsBrokenEvita them
Variable redeclarationBroken in else-ifUnique names or declare before if
Object.IsAlive()Not on base ObjectCast to EntityAI first
nullptrNonull / NULL
switch fall-throughNoEach case is independent
Predefinito param expressionsNoLiterals or NULL only
#define valuesNoconst
InterfacesNoEmpty classe base
Generic constraintsNoRuntime type checks
Enum validationNoManual range check
Variadic paramsNostring.Format or arrays
Nested classesNoTop-level with prefixed names
Variable-size static arraysNoarray<T>
#includeNoconfig.cpp files[]
NamespacesNoName prefixes
RAIINoManual cleanup
GetGame().GetPlayer() serverRestituisce nullIterate GetPlayers()
Ereditarieta classi sealed (1.28+)Errore di compilazioneUsa la composizione
17+ parametri metodo (1.28+)Errore di compilazionePassa una classe o un array
API [Obsolete] (1.28+)Avviso del compilatoreMigra all'API sostitutiva
Confronti int.MINRisultati erratiUsa una costante memorizzata
Negazione !array[i]Errore di compilazioneUsa array[i] == 0
Espr. complessa in assegnazione arraySegfaultUsa variabile intermedia
foreach su ritorno metodoCrash null pointerMemorizza prima in variabile locale
Precedenza bitwise vs confrontoValutazione errataUsa sempre le parentesi
Blocchi #ifdef vuotiSegfaultAggiungi un'istruzione o rimuovi il blocco
IsClient() durante il caricamentoRestituisce falseUsa IsDedicatedServer()
Errore compilazione file sbagliatoPosizione fuorvianteControlla il file analizzato dopo
File crash_*.logNon sono crash realiSono eccezioni runtime di script

PrecedenteUpSuccessivo
1.11 Error HandlingPart 1: Enforce Script1.13 Funzioni e Metodi

Released under CC BY-SA 4.0 | Code examples under MIT License