使用协议参数化的通用Swift类在运行时失败。为什么?

使用协议参数化的通用Swift类在运行时失败。为什么?,swift,generics,Swift,Generics,给出了两个等级A和PC以及协议p: 这也可以很好地编译 但是,当我运行它,并尝试通过pc将其转换为T时,调试器将进入: swift_dynamicCastUnknownClassUnconditional: [...] 0x105fedf76: leaq 0x3680f(%rip), %rax ; "bad metadata kind!" 为什么会这样 我假设,因为T受p约束,PC采用p,所以每个PC也必须是T 其他信息如下: let a = A<PC>() //

给出了两个等级A和PC以及协议p:

这也可以很好地编译

但是,当我运行它,并尝试通过pc将其转换为T时,调试器将进入:

swift_dynamicCastUnknownClassUnconditional:
[...]
0x105fedf76:  leaq   0x3680f(%rip), %rax       ; "bad metadata kind!"
为什么会这样

我假设,因为T受p约束,PC采用p,所以每个PC也必须是T

其他信息如下:

let a = A<PC>() // parametrized with the *class*, not the protocol
a.test()

工作起来很有魅力。

我并不奇怪这段代码有问题,即使它看起来应该在运行时工作,而且您可能应该重构它以不同的方式处理问题。这可能值得一个雷达,但我认为这是有争议的。归根结底,我不相信这句话:

let t = pc as T
这是一件值得做的事。也就是说,无论pc是什么,我都希望它是T型的。但这并不能保证是可以的。那么以下内容呢:

extension String: P { }
let x = A<String>()
上面的声明是完全可以接受的–String符合p,因此您可以创建一个A,其中T是String。但是你不能写让pc=pc;设t=pc为String–pc和String是完全不相关的类型。如果您试图在非泛型代码中执行此操作,则会出现编译器错误。对于泛型版本,您处于一种阴暗世界——泛型函数应该像在编译时说的那样,假设T被替换为实际类型,为我编写一个这样的函数。在这种情况下,as T应该如何解释还不清楚——它可能在编译时失败,也可能不会

现在你可能会说这没关系,我总是确保在调用create我的类时,我只使用可以工作的类型。它永远不会崩溃,因为我永远不会用会崩溃的东西来称呼它。你的例子就是这样


但这不是Swift泛型的操作方式——Swift尽其所能确保泛型中发生的事情对于任何符合泛型标准的类型都是有效的。只是因为,按照您在这里调用它的方式,它恰好起作用,并且您确信Swift让它编译并不能使代码有效,因此,您观察到的行为对我来说似乎是合理的。

感谢您提供了一个示例,使我的思想明显偏离了方向。。
let t = pc as T
extension String: P { }
let x = A<String>()