c_sharp_variant.rst 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. .. _doc_c_sharp_variant:
  2. C# Variant
  3. ==========
  4. For a detailed explanation of Variant in general, see the :ref:`Variant <class_Variant>` documentation page.
  5. ``Godot.Variant`` is used to represent Godot's native :ref:`Variant <class_Variant>` type. Any
  6. :ref:`Variant-compatible type <c_sharp_variant_compatible_types>` can be converted from/to it.
  7. We recommend avoiding ``Godot.Variant`` unless it is necessary to interact with untyped engine APIs.
  8. Take advantage of C#'s type safety when possible.
  9. Converting from a Variant-compatible C# type to ``Godot.Variant`` can be done using implicit
  10. conversions. There are also ``CreateFrom`` method overloads and the generic ``Variant.From<T>``
  11. methods. Only the syntax is different: the behavior is the same.
  12. .. code-block:: csharp
  13. int x = 42;
  14. Variant numberVariant = x;
  15. Variant helloVariant = "Hello, World!";
  16. Variant numberVariant2 = Variant.CreateFrom(x);
  17. Variant numberVariant3 = Variant.From(x);
  18. Implicit conversions to ``Godot.Variant`` make passing variants as method arguments very convenient.
  19. For example, the third argument of :ref:`tween_property<class_Tween_method_tween_property>`
  20. specifying the final color of the tween is a ``Godot.Variant``.
  21. .. code-block:: csharp
  22. Tween tween = CreateTween();
  23. tween.TweenProperty(GetNode("Sprite"), "modulate", Colors.Red, 1.0f);
  24. Converting from ``Godot.Variant`` to a C# type can be done using explicit conversions. There are
  25. also ``Variant.As{TYPE}`` methods and the generic ``Variant.As<T>`` method. All of these behave the
  26. same.
  27. .. code-block:: csharp
  28. int number = (int)numberVariant;
  29. string hello = (string)helloVariant;
  30. int number2 = numberVariant.As<int>();
  31. int number3 = numberVariant.AsInt32();
  32. .. note::
  33. The ``Variant.As{TYPE}`` methods are typically named after C# types (``Int32``), not C# keywords
  34. (``int``).
  35. If the Variant type doesn't match the conversion target type, the consequences vary depending on the
  36. source and target values.
  37. - The conversion may examine the value and return a similar but potentially unexpected value of the
  38. target type. For example, the string ``"42a"`` may be converted to the integer ``42``.
  39. - The default value of the target type may be returned.
  40. - An empty array may be returned.
  41. - An exception may be thrown.
  42. Converting to the correct type avoids complicated behavior and should be preferred.
  43. The ``Variant.Obj`` property returns a C# ``object`` with the correct value for any variant. This
  44. may be useful when the type of Variant is completely unknown. However, when possible, prefer more
  45. specific conversions. ``Variant.Obj`` evaluates a ``switch`` on ``Variant.VariantType`` and it may
  46. not be necessary. Also, if the result is a value type, it is boxed.
  47. For example, if the potential for ``Variant.As<MyNode>()`` to throw an invalid cast exception isn't
  48. acceptable, consider using a ``Variant.As<GodotObject>() is MyNode n`` type pattern instead.
  49. .. note::
  50. Since the Variant type in C# is a struct, it can't be null. To create a "null"
  51. Variant, use the ``default`` keyword or the ``Godot.Variant`` parameterless constructor.
  52. .. _c_sharp_variant_compatible_types:
  53. Variant-compatible types
  54. ------------------------
  55. A Variant-compatible type can be converted to and from a ``Godot.Variant``.
  56. These C# types are Variant-compatible:
  57. * All the `built-in value types <https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/built-in-types-table>`_,
  58. except ``decimal``, ``nint`` and ``nuint``.
  59. * ``string``.
  60. * Classes derived from :ref:`GodotObject <class_Object>`.
  61. * Collections types defined in the ``Godot.Collections`` namespace.
  62. Full list of Variant types and their equivalent C# type:
  63. ======================= ===========================================================
  64. Variant.Type C# Type
  65. ======================= ===========================================================
  66. ``Nil`` ``null`` (Not a type)
  67. ``Bool`` ``bool``
  68. ``Int`` ``long`` (Godot stores 64-bit integers in Variant)
  69. ``Float`` ``double`` (Godot stores 64-bit floats in Variant)
  70. ``String`` ``string``
  71. ``Vector2`` ``Godot.Vector2``
  72. ``Vector2I`` ``Godot.Vector2I``
  73. ``Rect2`` ``Godot.Rect2``
  74. ``Rect2I`` ``Godot.Rect2I``
  75. ``Vector3`` ``Godot.Vector3``
  76. ``Vector3I`` ``Godot.Vector3I``
  77. ``Transform2D`` ``Godot.Transform2D``
  78. ``Vector4`` ``Godot.Vector4``
  79. ``Vector4I`` ``Godot.Vector4I``
  80. ``Plane`` ``Godot.Plane``
  81. ``Quaternion`` ``Godot.Quaternion``
  82. ``Aabb`` ``Godot.Aabb``
  83. ``Basis`` ``Godot.Basis``
  84. ``Transform3D`` ``Godot.Transform3D``
  85. ``Projection`` ``Godot.Projection``
  86. ``Color`` ``Godot.Color``
  87. ``StringName`` ``Godot.StringName``
  88. ``NodePath`` ``Godot.NodePath``
  89. ``Rid`` ``Godot.Rid``
  90. ``Object`` ``Godot.GodotObject`` or any derived type.
  91. ``Callable`` ``Godot.Callable``
  92. ``Signal`` ``Godot.Signal``
  93. ``Dictionary`` ``Godot.Collections.Dictionary``
  94. ``Array`` ``Godot.Collections.Array``
  95. ``PackedByteArray`` ``byte[]``
  96. ``PackedInt32Array`` ``int[]``
  97. ``PackedInt64Array`` ``long[]``
  98. ``PackedFloat32Array`` ``float[]``
  99. ``PackedFloat64Array`` ``double[]``
  100. ``PackedStringArray`` ``string[]``
  101. ``PackedVector2Array`` ``Godot.Vector2[]``
  102. ``PackedVector3Array`` ``Godot.Vector3[]``
  103. ``PackedVector4Array`` ``Godot.Vector4[]``
  104. ``PackedColorArray`` ``Godot.Color[]``
  105. ======================= ===========================================================
  106. .. warning::
  107. Godot uses 64-bit integers and floats in Variant. Smaller integer and float types
  108. such as ``int``, ``short`` and ``float`` are supported since they can fit in the
  109. bigger type. Be aware that when a conversion is performed, using the wrong
  110. type will result in potential precision loss.
  111. .. warning::
  112. Enums are supported by ``Godot.Variant`` since their underlying type is an integer
  113. type which are all compatible. However, implicit conversions don't exist, enums must
  114. be manually converted to their underlying integer type before they can converted to/from
  115. ``Godot.Variant`` or use the generic ``Variant.As<T>`` and ``Variant.From<T>`` methods
  116. to convert them.
  117. .. code-block:: csharp
  118. enum MyEnum { A, B, C }
  119. Variant variant1 = (int)MyEnum.A;
  120. MyEnum enum1 = (MyEnum)(int)variant1;
  121. Variant variant2 = Variant.From(MyEnum.A);
  122. MyEnum enum2 = variant2.As<MyEnum>();
  123. Using Variant in a generic context
  124. ----------------------------------
  125. When using generics, you may be interested in restricting the generic ``T`` type to be
  126. only one of the Variant-compatible types. This can be achieved using the ``[MustBeVariant]``
  127. attribute.
  128. .. code-block:: csharp
  129. public void MethodThatOnlySupportsVariants<[MustBeVariant] T>(T onlyVariant)
  130. {
  131. // Do something with the Variant-compatible value.
  132. }
  133. Combined with the generic ``Variant.From<T>`` allows you to obtain an instance of ``Godot.Variant``
  134. from an instance of a generic ``T`` type. Then it can be used in any API that only supports the
  135. ``Godot.Variant`` struct.
  136. .. code-block:: csharp
  137. public void Method1<[MustBeVariant] T>(T variantCompatible)
  138. {
  139. Variant variant = Variant.From(variantCompatible);
  140. Method2(variant);
  141. }
  142. public void Method2(Variant variant)
  143. {
  144. // Do something with variant.
  145. }
  146. In order to invoke a method with a generic parameter annotated with the ``[MustBeVariant]``
  147. attribute, the value must be a Variant-compatible type or a generic ``T`` type annotated
  148. with the ``[MustBeVariant]`` attribute as well.
  149. .. code-block:: csharp
  150. public class ObjectDerivedClass : GodotObject { }
  151. public class NonObjectDerivedClass { }
  152. public void Main<[MustBeVariant] T1, T2>(T1 someGeneric1, T2 someGeneric2)
  153. {
  154. MyMethod(42); // Works because `int` is a Variant-compatible type.
  155. MyMethod(new ObjectDerivedClass()); // Works because any type that derives from `GodotObject` is a Variant-compatible type.
  156. MyMethod(new NonObjectDerivedClass()); // Does NOT work because the type is not Variant-compatible.
  157. MyMethod(someGeneric1); // Works because `T1` is annotated with the `[MustBeVariant]` attribute.
  158. MyMethod(someGeneric2); // Does NOT work because `T2` is NOT annotated with the `[MustBeVariant]` attribute.
  159. }
  160. public void MyMethod<[MustBeVariant] T>(T variant)
  161. {
  162. // Do something with variant.
  163. }