Skip to main content

别用 Enum,尽管会让你的代码更好看

别听标题的,你得用 Enum。但是你要注意以下所有的问题:

不要指望用户定义的 Enum 的 ToString() 能正常工作

public enum UserEnumType {
  One,
  Two
}

UserEnumType enumValue = UserEnumType.One;
Debug.Log(enumValue.One) // Output: 0 (????!)

不要把 Enum 类型转换和操作符/方法参数(可能还有其他的)写在一起

注:也可能有其他 U# 编译器不会进行类型转换的场景,请注意

相关 Feedback: https://feedback.vrchat.com/udon/p/converting-enum-to-int-in-datatoken-parameter-errors-at-runtime

// Cannot retrieve heap variable of type 'Int32' as type 'DataToken'
DataList dataList = new DataList();
AnEnum anEnumState = AnEnum.AState;
dataList.Add((int)anEnumState);
// Cannot retrieve heap variable of type 'Int32' as type 'byte'
Foo(EnumType e) {
  byte bar = 0;
  bar += (byte)e;
}

Workaround

EnumType enumType = EnumType.One;
int enumAsInt = (int)enumType; // 无论如何都不能跳过这个,必须先转成 Int

// 之后做你想做的
byte enumAsByte = (byte)enumAsInt;

不要在可选方法参数使用 Enum

Feedback: https://feedback.vrchat.com/udon/p/udonsharp-enum-as-optional-argument-causes-compile-errors

enum AnEnum {
    Option,
    AnotherOption
}

public class Test : UdonSharpBehaviour
{
    void OptionalEnum(AnEnum anEnum = AnEnum.Option) // Compile Error
    {
        
    }
}

编者:貌似修了,至少我测试了没问题。但是不保证一定能用。

不要对着非用户定义 Enum 做比较(==/=>/<=/!=)操作

Feedback: https://feedback.vrchat.com/udon/p/checking-a-system-defined-enum-with-equality-operators-fails

public override void OnInputMethodChanged(VRCInputMethod inputMethod)  
{  
    if (inputMethod == VRCInputMethod.Touch)  
    {  
        // Run code for touch input  
    }  
    else  
    {  
        // Run code for non-touch input  
    }  
}

当然也有 Workaround

if ((int)inputMethod == (int)VRCInputMethod.Touch)

也不要对着用户定义 Enum 做比较(==/=>/<=/!=)操作

我这看起来好像和上一条重复了,但是用户定义的 enum 有一些奇怪的行为

Feedback: https://feedback.vrchat.com/udon/p/enum-operator-gives-wrong-results-in-a-specific-case

public enum TestEnum
{
    ONE,
    TWO
}

var max = TestEnum.TWO;
Debug.Log(max >= TestEnum.TWO); // result: false (????!)

Debug.Log((int)max >= (int)TestEnum.TWO); // result: true

Debug.Log(TestEnum.TWO >= TestEnum.TWO) // result: true (But this works??????)