Skip to main content

Method calls

Besides ordinary colon / dot calls, three situations come up often when Lua calls C#:

TopicOne lineDeeper
Method overloadsMatch by args by default; use a full-signature key or [LuaAlias] when ambiguousMethod overloads
Generic methodsClose method-level <T> with inflate / GTAPGenerics
paramsExpand multiple slots, or pass a whole T[] userdata; no tableparams parameters

Day-to-day static / instance calls: Quick start, Lua calling C#.


1. Method overloads​

Lua has no compile-time overload selection. Same-name signatures match by arguments by default; name one explicitly with a full-signature key or a Bind-time alias.

Default (prefer this)​

demo:Run(10) -- Run(int)
demo:Run("hello") -- Run(string)

Multiple candidates use dispatch; a single public candidate is direct (no dispatch).

Exact pick​

demo['Run(System.Int32)'](demo, 10)

Keys with parentheses need bracket indexing and an explicit self. The method name is CLR MethodInfo.Name (not a [LuaAlias] short name).

Colon + short name​

Annotate with [LuaAlias("run_i32")] (or Alias XML); after Bind you can call demo:run_i32(10). There is no runtime API to hang short names. See LuaAlias.

Default parameters, lazy full-signature caching, and troubleshooting: Method overloads (guide).


2. Generic methods​

As in C#, start by telling these two cases apart:

CaseExampleIn Lua
Closed generic type, call an ordinary method on itList<int>.Addmake_generic_type first, then call like any instance method
Method itself has type parametersNameOf<T>() / GetComponent<T>()Close the method’s T with inflate or GTAP

2.1 Ordinary methods on a generic type​

Once the declaring type’s T is closed on the type side, members are not “open generic methods” — no inflate / GTAP:

-- Close once at module load / init and cache
local ListInt = zlua.make_generic_type(
CSharp.mscorlib['System.Collections.Generic.List`1'],
zlua.types.int32
)

local list = ListInt()
list:Add(10)
list:Add(20)
tip

make_generic_type is interned, but do not call it with the same arguments inside a hot loop; keep tables such as ListInt in an upvalue / module field.

2.2 Methods with their own type parameters​

The short name stays open until you close it. Assume C#:

public class Sample
{
public static string NameOf<T>() => typeof(T).Name;
public T Echo<T>(T value) => value;
}

zlua.inflate (prefer on hot paths):

local Sample = CSharp.AC.Sample

local NameOfInt = zlua.inflate(Sample, "NameOf", zlua.types.int32)
print(NameOfInt())

local sample = Sample()
local EchoStr = zlua.inflate(Sample, "Echo", zlua.types.string)
print(EchoStr(sample, "hi"))
warning

Do not inflate in a loop. On hot paths also avoid type-name strings as typeArg; prefer type tables / zlua.types.*.

-- ✗
for i = 1, n do
zlua.inflate(Sample, "Echo", zlua.types.string)(sample, "hi")
end

GTAP (convenient for occasional calls): prefixes must be System.Type (zlua.typeof); do not pass a type table directly.

print(Sample.NameOf(zlua.typeof(zlua.types.int32)))
print(sample:Echo(zlua.typeof(zlua.types.string), "hi"))
warning

Avoid GTAP on hot paths. Every call takes the open-method prefix path; for Update / combat, cache the closure from inflate.

PathNotes
inflateClose first, then call; preferred on hot paths
GTAPShort name + typeof prefixes; occasional use

2.3 Example: GameObject.GetComponent​

local UE = CSharp['UnityEngine.CoreModule']
local GameObject = UE['UnityEngine.GameObject']
local Rigidbody = UE['UnityEngine.Rigidbody']

local GetRb = zlua.inflate(GameObject, "GetComponent", Rigidbody)
local rb = GetRb(go)

-- Occasional GTAP also works:
-- local rb = go:GetComponent(zlua.typeof(Rigidbody))
warning

Do not GTAP / inflate every frame in Update. Close once at startup; on the hot path only call GetRb(go).

CallMeaning
go:GetComponent(zlua.typeof(Rigidbody))GTAP → GetComponent<Rigidbody>()
go:GetComponent(Rigidbody)Wrong (type table as a normal argument)
go:GetComponent("UnityEngine.Rigidbody")Hits a string overload if present — not generic close

After close, the declared return is often Component; for an actual-type view see Return view type. More: Generics.


3. params parameters​

Trailing C# params T[] may expand multiple Lua args, or take a whole T[] userdata. Unlike ordinary array formals: no Lua table / lone nil as the whole array.

static void Sum(params int[] values) { }
static void Prefix(int head, params int[] tail) { }
Demo.Sum(1, 2, 3) -- expand → int[]{1,2,3}
Demo.Sum() -- → int[0]
Demo.Prefix(0, 1, 2)

-- Whole userdata
Demo.Sum(arr) -- arr is int[] ByObjUserData

-- ✗ Demo.Sum({ 1, 2, 3 }) -- table not allowed
-- ✗ Demo.Sum(nil) -- not a null array

When overloads coexist, fixed-arity candidates usually beat params expansion. Full rules: params parameters.


Next​

TopicGuide
Overloads / defaults / full-signature keysMethod overloads
Closed types and generic methodsGenerics
params expand / whole array / unsupported scopeparams parameters
Alias short namesLuaAlias