C# Variant
对于 Variant 的详细解释,请参阅 Variant 文档页面。
Godot.Variant
用于表示 Godot 的原生 Variant 类型。任何 Variant 兼容类型 都可以和它进行转换。我们建议仅在与无类型的引擎 API 交互时使用 Godot.Variant
。尽可能利用 C# 的类型安全性。
将 Variant 兼容的 C# 类型转换为 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
属性返回一个 C# object
,其中包含任何变体的正确值。当变体的类型完全未知时,这可能很有用。但是,如果可能,最好使用更具体的转换。Variant.Obj
会关于 Variant.VariantType
执行一个 switch
,这可能不是必需的。此外,如果结果是值类型,则会对其进行装箱。
例如,如果 Variant.As<MyNode>()
引发一个无效转换异常的可能性是不可接受的,请考虑改用 Variant.As<GodotObject>() is MyNode n
类型模式。
备注
由于 C# 中的 Variant 类型是一个结构体,它不能为 null。要创建一个 “null” Variant,请使用 default
关键字或 Godot.Variant
无参数构造函数。
Variant 兼容类型
Variant 兼容类型可以与 Godot.Variant
相互转换。以下 C# 类型与 Variant 兼容:
除了
decimal
、nint
和nuint
之外,所有的 内置值类型 。String
。从 GodotObject 派生的类。
在
Godot.Collections
命名空间中定义的集合类型。
Variant 类型的完整列表及其对应的 C# 类型:
Variant.Type |
C# 类型 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
警告
Godot 在 Variant 中使用 64 位的整数和浮点数。较小的整数和浮点数类型,如 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>();
在泛型上下文中使用 Variant
在使用泛型时,你可能希望限制泛型 T
类型仅为 Variant 兼容类型之一。这可以通过使用 [MustBeVariant]
特性来实现。
public void MethodThatOnlySupportsVariants<[MustBeVariant] T>(T onlyVariant)
{
// Do something with the Variant-compatible value.
}
结合泛型 Variant.From<T>
可以让你从一个泛型 T
类型的实例中获取一个 Godot.Variant
的实例。然后它可以用在任何只支持 Godot.Variant
结构体的 API 中。
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 兼容类型或者带有 [MustBeVariant]
特性标注的泛型 T
类型。
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.
}