Conversions
Forms that compile (23)
Section titled “Forms that compile (23)”Forms that don’t compile (17)
Section titled “Forms that don’t compile (17)”| Syntax | Description | Error | Reason | Instead |
|---|---|---|---|---|
int? a = 1; | A type meaning a value or null | TUKI0001, TUKI0101, TUKI0102 | runtime | Use a separate variable to hold whether a value is present |
int b = (int)a; | Extract the value from a value-or-null type | TUKI0102, TUKI0001, TUKI0099 | runtime | Same as above |
long? b = a; | Convert between value-or-null types (a lifted conversion) | TUKI0001, TUKI0101, TUKI0102 | runtime | Same as above |
dynamic d = 1; | Determine the type at runtime | TUKI0102, TUKI0099 | runtime | Write the type |
(long, long) b = a; | Convert between tuples element by element | TUKI0099 | not yet | Move the elements one at a time |
((int, int))a | Explicitly convert a tuple | TUKI0099 | not yet | Same as above |
(T)value | Convert from object back to a type parameter | TUKI0099 | undecided | Rewrite it without using a type parameter |
public static implicit operator float(Meters m) | Define your own implicit conversion | TUKI0001 | not yet | Write a conversion method and call it |
public static explicit operator int(Meters m) | Define your own explicit conversion | TUKI0001 | not yet | Same as above |
System.Action a = Helper; | Turn a method name into a delegate | TUKI0108 | runtime | Pass the method name and call it (SendCustomEvent) |
delegate(int x) { … } | Write a function inline as a value | TUKI0108, TUKI0001 | runtime | Same as above |
throw new System.Exception() | Throw an exception (as an expression or a statement) | TUKI0001, TUKI0101 | runtime | Represent failure with a return value or state |
System.FormattableString s = $"…"; | Hold an interpolated string as a formatting target | TUKI0102, TUKI0101, TUKI0099 | runtime | Build it as a string |
System.Span<int> s = a; | Borrow a view of a contiguous region | TUKI0102, TUKI0101, TUKI0099 | runtime | Use the array directly |
c as Transform | Become null if the conversion fails | TUKI0001 | not yet | Receive it with a union type pattern (s switch { Box b => … }) |
o is Transform | Ask at runtime about a type that may have derived types | TUKI0001 | by design | If the type is known, write a cast ((Transform)o). If it’s a union or an interface, receive it with a type pattern. |
IProducer<IThing> q = p; | Convert a generic interface based on the derivation relation of its type parameter (variance) | TUKI0001 | undecided | Generic interfaces only work for declaration and implementation. Rewrite it in a form that doesn’t use it as a value. |
The type meaning “a value or null” can’t be used. That type doesn’t exist in the runtime (TUKI0102). The form of ?. that returns a value type doesn’t compile either, because the result would be this type. |
Conversions determined by the target type apply to default, new(), ?:, and switch expressions. All of them convert to the type on the left-hand side.
Tuples can be declared, but conversion between tuples isn’t possible (TUKI0099).
Same type and numbers
Section titled “Same type and numbers”Conversion to the same type
Section titled “Conversion to the same type”using UnityEngine;using Tsukimi;
public class CvIdentity : TsukimiBehaviour{ void Start() { int a = 1; int b = a; Debug.Log(b); // => 1 }}Implicit conversion to a wider type
Section titled “Implicit conversion to a wider type”using UnityEngine;using Tsukimi;
public class ConversionsImplicitNumeric : TsukimiBehaviour{ void Start() { int a = 1; long b = a; float c = a; double d = c; Debug.Log(b + c + d); // => 3 }}Conversion of a constant that fits the range
Section titled “Conversion of a constant that fits the range”A constant that fits the range can be assigned to a narrower type without a cast. A variable can’t be assigned the same way.
using UnityEngine;using Tsukimi;
public class CvConstantExpr : TsukimiBehaviour{ void Start() { byte b = 200; short s = 30000; Debug.Log(b + s); // => 30200 }}Explicit conversion to a narrower type
Section titled “Explicit conversion to a narrower type”The result of passing a value outside the range is in Numerics. For conversion from a floating-point type to an integer type, a value outside the range stops execution.
using UnityEngine;using Tsukimi;
public class ConversionsExplicitNumeric : TsukimiBehaviour{ void Start() { double d = 1.9; int a = (int)d; byte b = (byte)a; Debug.Log(a + b); // => 2 }}Conversion between char and numeric types
Section titled “Conversion between char and numeric types”char converts to int without a cast. Converting back from int to char requires a cast.
using UnityEngine;using Tsukimi;
public class ConversionsCharAndInt : TsukimiBehaviour{ void Start() { char c = 'a'; int a = c; char d = (char)(a + 1); Debug.Log(d); // => b }}Conversion of the constant 0 to an enum
Section titled “Conversion of the constant 0 to an enum”Only the constant 0 converts implicitly. Other numbers require a cast.
using UnityEngine;using Tsukimi;
public enum Mode { Off, On }public class CvImplicitEnumZero : TsukimiBehaviour{ void Start() { Mode m = 0; Debug.Log((int)m); // => 0 }}Conversion from an enum to a number
Section titled “Conversion from an enum to a number”using UnityEngine;using Tsukimi;
public enum Mode { A, B }
public class ConversionsEnumToInt : TsukimiBehaviour{ void Start() { Mode m = Mode.B; int a = (int)m; Debug.Log(a); // => 1 }}Conversion from a number to an enum
Section titled “Conversion from a number to an enum”using UnityEngine;using Tsukimi;
public enum Mode { A, B }
public class ConversionsIntToEnum : TsukimiBehaviour{ void Start() { int a = 1; Mode m = (Mode)a; Debug.Log(m == Mode.B); // => true }}Conversion between enums
Section titled “Conversion between enums”using UnityEngine;using Tsukimi;
public enum A { Zero, One }public enum B { Zero, One }public class CvEnumToEnum : TsukimiBehaviour{ void Start() { A a = A.One; B b = (B)a; Debug.Log((int)b); // => 1 }}Boxing
Section titled “Boxing”Boxing a value type
Section titled “Boxing a value type”When a value type is placed into object, it’s held as a reference.
using UnityEngine;using Tsukimi;
public class ConversionsBoxing : TsukimiBehaviour{ void Start() { int a = 1; object o = a; Debug.Log(o); // => 1 }}Unboxing
Section titled “Unboxing”using UnityEngine;using Tsukimi;
public class ConversionsUnboxing : TsukimiBehaviour{ void Start() { object o = 1; int a = (int)o; Debug.Log(a); // => 1 }}Checking the type of the contents
Section titled “Checking the type of the contents”is checks the type of object’s contents at runtime. This works only when the value is object and the type being checked is a number, bool, char, or string.
using UnityEngine;using Tsukimi;
public class ConversionsIsGeneralType : TsukimiBehaviour{ void Start() { object o = 1; bool b = o is int; Debug.Log(b); // => true }}Reference types and interfaces
Section titled “Reference types and interfaces”Conversion to a base type
Section titled “Conversion to a base type”using UnityEngine;using Tsukimi;
public class ConversionsReferenceWidening : TsukimiBehaviour{ public Transform target;
void Start() { Component c = target; Debug.Log(c == null); // => a runtime value }}Conversion to an interface type
Section titled “Conversion to an interface type”using UnityEngine;using Tsukimi;
public interface IThing { int Get(); }public struct Impl : IThing { public int Get() { return 1; } }public class CvImplicitToInterface : TsukimiBehaviour{ void Start() { Impl v = new Impl(); IThing t = v; Debug.Log(t.Get()); // => 1 }}Conversion from object to a reference type
Section titled “Conversion from object to a reference type”Convert a reference-type value held in object back to its original type.
using UnityEngine;using Tsukimi;
public class ConversionsObjectToConcrete : TsukimiBehaviour{ void Start() { object o = null; Transform t = (Transform)o; Debug.Log(t == null); // => a runtime value }}Assigning null
Section titled “Assigning null”using UnityEngine;using Tsukimi;
public class CvNullLiteral : TsukimiBehaviour{ void Start() { string s = null; Debug.Log(s == null); // => true }}Type parameters
Section titled “Type parameters”Conversion from a type parameter to object
Section titled “Conversion from a type parameter to object”A type parameter’s value converts to object. Converting from object back to a type parameter can’t be written.
using UnityEngine;using Tsukimi;
public class CvTypeParamImplicit : TsukimiBehaviour{ void Start() { Debug.Log(ToObject<int>(1)); // => 1 }
private object ToObject<T>(T value) { return value; }}Conversions determined by the target type
Section titled “Conversions determined by the target type”Writing default
Section titled “Writing default”using UnityEngine;using Tsukimi;
public class CvDefaultLiteral : TsukimiBehaviour{ void Start() { int a = default; string s = default; Debug.Log(a); // => 0 }}Creation with the type name omitted
Section titled “Creation with the type name omitted”using UnityEngine;using Tsukimi;
public struct Holder { public int V; }public class CvImplicitNew : TsukimiBehaviour{ void Start() { Holder h = new(); Debug.Log(h.V); // => 0 }}Matching types on both sides of ?:
Section titled “Matching types on both sides of ?:”using UnityEngine;using Tsukimi;
public class CvImplicitConditional : TsukimiBehaviour{ void Start() { bool c = true; long v = c ? 1 : 2; Debug.Log(v); // => 1 }}Matching types across switch expression cases
Section titled “Matching types across switch expression cases”using UnityEngine;using Tsukimi;
public class CvSwitchExprConv : TsukimiBehaviour{ void Start() { int k = 1; long v = k switch { 1 => 10, _ => 20 }; Debug.Log(v); // => 10 }}Strings
Section titled “Strings”Conversion to a string
Section titled “Conversion to a string”ToString() converts a value to a string. A number with no specified format uses the default format.
using UnityEngine;using Tsukimi;
public class ConversionsToString : TsukimiBehaviour{ void Start() { int a = 1; string s = a.ToString(); Debug.Log(s); // => "1" }}Reading from a string
Section titled “Reading from a string”using UnityEngine;using Tsukimi;
public class ConversionsParse : TsukimiBehaviour{ void Start() { int a = int.Parse("1"); Debug.Log(a); // => 1 }}