c_sharp_variant.rst 8.0 KB

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