Swift 可失败的 rawValue 初始值设定项复杂度

Swift failable rawValue initializer Complexity

我想知道枚举可失败初始化程序的时间复杂度

示例

enum Operator: Character {
  case parenthesis = "("
  case brace = "{"
  case bracket = "["
}

// Time Complexity?
if let op = Operator(rawValue: "[") {
  ...
}

请注意,这是一个非常重要的实现细节,因为文档没有说明。

使用我的 Swift 编译器版本 5.3.2,我将您的枚举(使用 -Ounchecked)编译为二进制文件,并使用 Hopper Disassembler 检查它以查看为原始值初始化程序生成的代码.初始化程序实际上什么都不做,只是直接跳转到另一个过程。该过程看起来像这样:

// pseudo code generated by Hopper
int _$s4main3FooO8rawValueACSgSJ_tcfCTf4nd_n(int arg0, int arg1, int arg2, int arg3, int arg4) {
    r12 = arg1;
    r15 = arg0;
    if ((arg0 == 0x28) && (r12 == 0xe100000000000000)) {
            swift_bridgeObjectRelease(r12);
            rbx = 0x0;
    }
    else {
            if ((Swift._stringCompareWithSmolCheck(0x28, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
                    swift_bridgeObjectRelease(r12);
                    rbx = 0x0;
            }
            else {
                    if ((r15 == 0x7b) && (r12 == 0xe100000000000000)) {
                            swift_bridgeObjectRelease(r12);
                            rbx = 0x1;
                    }
                    else {
                            if ((Swift._stringCompareWithSmolCheck(0x7b, 0xe100000000000000, r15, r12, 0x0) & 0x1) != 0x0) {
                                    swift_bridgeObjectRelease(r12);
                                    rbx = 0x1;
                            }
                            else {
                                    if (r15 == 0x5b) {
                                            if (r12 == 0xe100000000000000) {
                                                    swift_bridgeObjectRelease(0xe100000000000000);
                                                    rbx = 0x2;
                                            }
                                            else {
                                                    rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
                                                    swift_bridgeObjectRelease(r12);
                                                    rbx = rbx & 0x1 ^ 0x3;
                                            }
                                    }
                                    else {
                                            rbx = Swift._stringCompareWithSmolCheck(0x5b, 0xe100000000000000, r15, r12, 0x0);
                                            swift_bridgeObjectRelease(r12);
                                            rbx = rbx & 0x1 ^ 0x3;
                                    }
                            }
                    }
            }
    }
    rax = rbx;
    return rax;
}

注意值 0x28、0x7b 和 0x5b。它们分别匹配 ({[ 的代码点。看起来该算法基本上是“检查参数是否按顺序匹配每个案例的原始值”。

我尝试添加更多的情况,if 嵌套更多,我可以看到我添加的字符的代码点。

所以看起来确实,更多的情况会导致 init(rawValue:) 在最坏的情况下花费更多的时间(请注意,这并不是算法的时间复杂度)。

但是,如果您使用 Int 作为原始值类型,则它不会执行所有这些复杂的字符串比较,因为它可以使用整数来表示您的枚举。如果您还让编译器推断原始值,则初始化程序将只进行范围检查。在这种情况下,添加更多案例(推断其原始值)不会增加初始化程序所花费的时间。

虽然在一天结束时,我认为执行时间的这一点增加根本不重要。您不会将 数百万 个案例添加到您的枚举中。