On Thu, 03 Dec 2015 21:55:04 +0000, Nordlöw wrote: > On Thursday, 3 December 2015 at 21:38:48 UTC, Chris Wright wrote: >> The terrible way is something like: >> >> void reset(Object o) >> in { >> assert(!(o is null)); >> } >> body { >> auto p = cast(ubyte*)*cast(void**)&o; >> auto ci = o.classinfo; >> auto init = cast(ubyte)ci.init; p[0..init.length] = init[]; >> if (ci.defaultConstructor) { >> ci.defaultConstructor(o); >> } else { >> throw new Exception("no default constructor; object is in >> invalid state"); >> } >> } > > In what way is this better than my solution?
I called my solution "terrible", which doesn't suggest that I think well of it compared to alternatives. I did this mainly to provide another implementation that someone else had alluded to. But since you asked... You're ignoring the distinction between runtime and compiletime types, and you are resetting fields to the default values of their types, not the default values of the fields. To wit: class Foo { int i = 5; } class Bar : Foo { int j = 6; this() {} this(int a, int b) { i = a; j = b; } } Foo foo = new Bar(10, 10); nordlow.resetAllFields(foo); We expect foo to look like a default-initialized instance of whatever it began life as. Like if we implemented the equality operations, we'd expect to see this work: `assert(foo == new Bar);` But we don't. Your solution doesn't know what the default field value of Foo.i is, so it erroneously resets it to 0. We wanted 5. Similarly, your solution ignores the fact that we've got an instance of Bar here, not an instance of Foo, and there are additional fields that need to be reset. You're using compile time reflection, so there's no way around that -- unless you create a virtual method with a mixin and require the user to mix it into each class in the hierarchy. My solution still gets a ton wrong. I forgot to call the destructor, for instance. I can't call the constructor if it has parameters, and that means the object might well be in an invalid state. It's not safe in the face of potential runtime changes. Assuming I encountered a case that both our solutions could handle correctly, I'd prefer yours. It's safer.