C# Variant
Подробное описание Variant в целом см. на странице документации Variant.
Godot.Variant используется для представления собственного типа Godot Variant. Любой Variant-compatible type может быть преобразован в него. Мы рекомендуем избегать Godot.Variant, если только это не требуется для взаимодействия с нетипизированными API движка. По возможности используйте преимущества типобезопасности C#.
Преобразование типа C#, совместимого с Variant, в Godot.Variant можно выполнить с помощью неявных преобразований. Существуют также перегрузки метода CreateFrom и универсальные методы Variant.From<T>. Различается только синтаксис, а поведение остаётся прежним.
int x = 42;
Variant numberVariant = x;
Variant helloVariant = "Hello, World!";
Variant numberVariant2 = Variant.CreateFrom(x);
Variant numberVariant3 = Variant.From(x);
Неявные преобразования в Godot.Variant делают передачу вариантов в качестве аргументов метода очень удобной. Например, третий аргумент tween_property, задающий конечный цвет анимации, — это Godot.Variant.
Tween tween = CreateTween();
tween.TweenProperty(GetNode("Sprite"), "modulate", Colors.Red, 1.0f);
Преобразование из Godot.Variant в тип C# можно выполнить с помощью явных преобразований. Существуют также методы Variant.As{TYPE} и универсальный метод Variant.As<T>. Все они ведут себя одинаково.
int number = (int)numberVariant;
string hello = (string)helloVariant;
int number2 = numberVariant.As<int>();
int number3 = numberVariant.AsInt32();
Примечание
Методы Variant.As{TYPE} обычно именуются по типам C# (Int32), а не по ключевым словам C# (int).
Если тип Variant не соответствует целевому типу конверсии, последствия различаются в зависимости от исходных и целевых значений.
Преобразование может проверить значение и вернуть похожее, но потенциально неожиданное значение целевого типа. Например, строка
"42a"может быть преобразована в целое число42.Может быть возвращено значение по умолчанию для целевого типа.
Может быть возвращен пустой массив.
Может быть выдано исключение.
Преобразование в правильный тип позволяет избежать сложного поведения и является предпочтительным.
Свойство Variant.Obj возвращает object C# с правильным значением для любого варианта. Это может быть полезно, когда тип варианта совершенно неизвестен. Однако, если возможно, предпочитайте более точные преобразования. Variant.Obj вычисляет switch для Variant.VariantType, и это может быть необязательно. Кроме того, если результат является типом значения, он упаковывается.
Например, если вероятность того, что Variant.As<MyNode>() выдаст недопустимое исключение приведения типов, неприемлема, рассмотрите возможность использования вместо этого шаблона типа Variant.As<GodotObject>() is MyNode n.
Примечание
Поскольку тип Variant в C# является структурой, он не может быть равен "null". Чтобы создать вариант со значением "null", используйте ключевое слово default или конструктор без параметров Godot.Variant.
Variant-compatible типы
Совместимый с Variant тип может быть преобразован в Godot.Variant и обратно. Следующие типы C# совместимы с Variant:
Все built-in value types (встроенные типы значений), кроме
decimal,nintиnuint.string.Классы, производные от GodotObject.
Типы коллекций, определенные в пространстве имен
Godot.Collections.
Полный список типов Variant и их эквивалентных типов C#:
Variant.Type |
C# Type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Предупреждение
Godot использует 64-битные целые числа и числа с плавающей точкой в Variant. Поддерживаются целые и числа с плавающей точкой меньшего размера, такие как int, short и float, поскольку они могут быть представлены в более крупном типе. Имейте в виду, что при преобразовании использование неправильного типа может привести к потенциальной потере точности.
Предупреждение
Перечисления поддерживаются в Godot.Variant, поскольку их базовый тип — целочисленный, и все они совместимы. Однако неявных преобразований не существует: перечислимые типы необходимо вручную преобразовать в базовый целочисленный тип, прежде чем их можно будет преобразовать в Godot.Variant или из него, или использовать универсальные методы Variant.As<T> и Variant.From<T> для их преобразования.
enum MyEnum { A, B, C }
Variant variant1 = (int)MyEnum.A;
MyEnum enum1 = (MyEnum)(int)variant1;
Variant variant2 = Variant.From(MyEnum.A);
MyEnum enum2 = variant2.As<MyEnum>();
Использование варианта в общем контексте
При использовании универсальных типов может возникнуть необходимость ограничить универсальный тип T только одним из типов, совместимых с Variant. Этого можно добиться с помощью атрибута [MustBeVariant].
public void MethodThatOnlySupportsVariants<[MustBeVariant] T>(T onlyVariant)
{
// Do something with the Variant-compatible value.
}
В сочетании с универсальным методом Variant.From<T> это позволяет получить экземпляр Godot.Variant из экземпляра универсального типа T. Затем его можно использовать в любом API, который поддерживает только структуру Godot.Variant.
public void Method1<[MustBeVariant] T>(T variantCompatible)
{
Variant variant = Variant.From(variantCompatible);
Method2(variant);
}
public void Method2(Variant variant)
{
// Do something with variant.
}
Чтобы вызвать метод с универсальным параметром, аннотированным атрибутом [MustBeVariant], значение должно быть типом, совместимым с Variant, или универсальным типом T, также аннотированным атрибутом [MustBeVariant].
public class ObjectDerivedClass : GodotObject { }
public class NonObjectDerivedClass { }
public void Main<[MustBeVariant] T1, T2>(T1 someGeneric1, T2 someGeneric2)
{
MyMethod(42); // Works because `int` is a Variant-compatible type.
MyMethod(new ObjectDerivedClass()); // Works because any type that derives from `GodotObject` is a Variant-compatible type.
MyMethod(new NonObjectDerivedClass()); // Does NOT work because the type is not Variant-compatible.
MyMethod(someGeneric1); // Works because `T1` is annotated with the `[MustBeVariant]` attribute.
MyMethod(someGeneric2); // Does NOT work because `T2` is NOT annotated with the `[MustBeVariant]` attribute.
}
public void MyMethod<[MustBeVariant] T>(T variant)
{
// Do something with variant.
}