I'm seeing some odd behaviour in a class I created a while ago, where it seems that a struct's properties are changing immediately after being passed (copied) to a method.
我在之前创建的类中看到了一些奇怪的行为,在这个类中,结构的属性在被传递(复制)到方法后立即发生变化。
I've boiled it down to a simple test case that can be run in a playground:
我把它归结为一个可以在操场上运行的简单测试用例:
struct StructToPass<T> {
let x: T
}
class MyClass<T> {
func createAndPassStructWithValue(value: T) {
let structToPass = StructToPass(x: value)
println("Before passing to method: \(structToPass.x)")
passStruct(structToPass)
}
func passStruct(_ theStruct: StructToPass<T>? = nil) {
println("Inside method: \(theStruct!.x)")
}
}
let myClass = MyClass<Int>()
myClass.createAndPassStructWithValue(42)
Looking at the relevant printed statements, it shows that the struct's x
property has changed:
看一下相关的打印报表,它显示了struct的x属性发生了变化:
// Before passing to method: 42
// Inside method: 140734543799888
Creating the struct outside the class and calling passStruct(_:)
directly causes the playground to crash, as does writing passStruct(_:)
as a function:
在类之外创建结构体并调用passStruct(_:)直接导致游乐场崩溃,将passStruct(_:)作为函数编写也一样:
// Causes playground to crash:
let aStruct = StructToPass(x: 42)
myClass.passStruct(aStruct)
// Also causes playground to crash:
func passStruct<T>(_ theStruct: StructToPass<T>? = nil) {}
passStruct(aStruct)
Changing the passStruct(_:)
method/function to use the default external parameter name fixes the issue, as does introducing another parameter (before/after the default parameter):
更改passStruct(_:)方法/函数以使用默认的外部参数名称来修复问题,同时引入另一个参数(在默认参数之前/之后):
// This works:
func passStruct<T>(theStruct: StructToPass<T>? = nil) {
println("Inside function: \(theStruct!.x)")
}
passStruct(theStruct: aStruct)
// This also works:
func passStruct<T>(_ theStruct: StructToPass<T>? = nil, someOtherParam: Int) {
println("Inside function: \(theStruct!.x)")
}
passStruct(aStruct, 42)
Is this a compiler bug? It seems the compiler doesn't like it when a generic function/method with a single argument with a default value doesn't use an external parameter name. It's a specific case, but I think it ought to work. If it shouldn't work, there ought to be a compiler warning.
这是编译错误吗?当具有默认值的单个参数的泛型函数/方法不使用外部参数名称时,编译器似乎不喜欢它。这是一个具体的案例,但我认为它应该行得通。如果它不应该工作,应该有一个编译器警告。
1 个解决方案
#1
2
110% compiler bug. I've even tried this out of Playground. It all happily compiles until you want to add a line which actually does something, like sending a passStruct. There's all kinds of things wrong with this. I even had this fail:
110%的编译器错误。我甚至在操场上试过。它会愉快地编译,直到您想要添加一个实际执行某些操作的行,比如发送passStruct。这有各种各样的问题。我甚至失败了:
func passStruct<T>(_ theStruct: StructToPass<T>? = (nil as StructToPass<T>?)) {
println("Inside function: \(theStruct!.x)")
}
which I kinda thought might be the problem (even though it shouldn't be I've had that elsewhere).
我认为这可能是问题所在(尽管我在别处应该没有)。
Well found! Report it. They're clearly not finished with generics. In my experiments I found that generic class properties aren't allowed.
准备好了的!报告。他们显然还没有完成泛型。在我的实验中,我发现不允许泛型类属性。
static let nilStruct: StructToPass<T>? = nil
does not compile, with one of the "not yet supported" error messages.
不编译,使用“尚未支持”的错误消息之一。
#1
2
110% compiler bug. I've even tried this out of Playground. It all happily compiles until you want to add a line which actually does something, like sending a passStruct. There's all kinds of things wrong with this. I even had this fail:
110%的编译器错误。我甚至在操场上试过。它会愉快地编译,直到您想要添加一个实际执行某些操作的行,比如发送passStruct。这有各种各样的问题。我甚至失败了:
func passStruct<T>(_ theStruct: StructToPass<T>? = (nil as StructToPass<T>?)) {
println("Inside function: \(theStruct!.x)")
}
which I kinda thought might be the problem (even though it shouldn't be I've had that elsewhere).
我认为这可能是问题所在(尽管我在别处应该没有)。
Well found! Report it. They're clearly not finished with generics. In my experiments I found that generic class properties aren't allowed.
准备好了的!报告。他们显然还没有完成泛型。在我的实验中,我发现不允许泛型类属性。
static let nilStruct: StructToPass<T>? = nil
does not compile, with one of the "not yet supported" error messages.
不编译,使用“尚未支持”的错误消息之一。