Skip to content

Variables and passing arguments

SyntaxDescription
int a = 1;Local variable
var a = 1;Type inference
int a = 1, b = 2;Combined declaration
{ int a = 1; }Scope from a block
int a; a = 1;Assign after declaring
private static int Counter;Static variable
int Take(int v)Pass by value
int Read(in int v)in parameter
int.TryParse("1", out n)out from a method on the runtime
out int nDeclare an out variable inline
if (…) a = 1; else a = 2;Assignment in if and else
switch … case … default …Assignment in every switch case
_ = Make();Discard a return value
SyntaxDescriptionErrorReasonInstead
Bump(ref a)Pass ref to a method you wroteTUKI0001not yetReturn it as a value
Make(out int a)Receive out from a method you wroteTUKI0001not yetReturn it as a value
Bump(ref a[0])Pass an array element by refTUKI0001not yetPass the value and write it back through the return value
ref int r = ref a;A local that points to the variable itselfTUKI0001undecidedHold a value
ref int First(int[] xs)Return the variable itselfTUKI0001undecidedReturn a value and write it back at the call site
r = ref b;Replace what it points toTUKI0001undecidedSame as above
ref (c ? ref a : ref b)Choose what it points to by a conditionTUKI0001undecidedSame as above
Make(out _);Discard the out destinationTUKI0001, TUKI0099not yetReceive it with a variable
int.TryParse("1", out _)Discard the out of a method on the runtimeTUKI0099not yetReceive it with a variable
Forms that hold a variable’s location itself as a value don’t compile. A ref local, a ref return, ref reassignment, and ref in a conditional expression all produce TUKI0001. Return the changed result as a value and assign it at the call site.

Definite assignment follows the same rules as C#. If every branch assigns it, it can be read afterward. Reading before assignment produces CS0165.

using UnityEngine;
using Tsukimi;
public class VarLocal : TsukimiBehaviour
{
void Start()
{
int a = 1;
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VarInferredType : TsukimiBehaviour
{
void Start()
{
var a = 1;
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VarMultipleDeclarators : TsukimiBehaviour
{
void Start()
{
int a = 1, b = 2;
Debug.Log(a + b); // => 3
}
}
using UnityEngine;
using Tsukimi;
public class VarBlockScope : TsukimiBehaviour
{
void Start()
{
{
int a = 1;
Debug.Log(a); // => 1
}
}
}

You can declare it alone and assign later. Reading before assignment is rejected with CS0165.

using UnityEngine;
using Tsukimi;
public class VarAssignBeforeUse : TsukimiBehaviour
{
void Start()
{
int a;
a = 1;
Debug.Log(a); // => 1
}
}

It belongs to the type, not the instance. The value is separate per behaviour instance, and isn’t shared between instances.

using UnityEngine;
using Tsukimi;
public class VaStatic : TsukimiBehaviour
{
void Start()
{
Counter = Counter + 1;
Debug.Log(Counter); // => 1
}
private static int Counter;
}

A copy of the value is passed to the parameter. Assigning to the parameter in the callee doesn’t change the caller’s variable.

using UnityEngine;
using Tsukimi;
public class VaValueParam : TsukimiBehaviour
{
void Start()
{
Debug.Log(Take(1)); // => 1
}
private int Take(int v) { return v; }
}

The declaration can state that the callee won’t assign to the parameter. Unlike ref and out, this can also be written on a method you wrote.

using UnityEngine;
using Tsukimi;
public class VarInParameter : TsukimiBehaviour
{
private int Read(in int v) { return v; }
void Start()
{
int a = 1;
Debug.Log(Read(in a)); // => 1
}
}

out can only be written when calling a method on the runtime. It can’t be written on a method you wrote (TUKI0001).

using UnityEngine;
using Tsukimi;
public class VarOutFromExtern : TsukimiBehaviour
{
void Start()
{
int n;
bool ok = int.TryParse("1", out n);
Debug.Log(ok ? n : 0); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VarOutDeclaredInline : TsukimiBehaviour
{
void Start()
{
bool ok = int.TryParse("1", out int n);
Debug.Log(ok ? n : 0); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VaDefAssignIf : TsukimiBehaviour
{
void Start()
{
int a;
if (true) { a = 1; } else { a = 2; }
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VaDefAssignSwitch : TsukimiBehaviour
{
void Start()
{
int k = 1;
int a;
switch (k) { case 1: a = 1; break; default: a = 0; break; }
Debug.Log(a); // => 1
}
}
using UnityEngine;
using Tsukimi;
public class VarDiscard : TsukimiBehaviour
{
private int calls;
void Start()
{
_ = Make();
Debug.Log(calls); // => 1
}
private int Make()
{
calls = calls + 1;
return 1;
}
}