On Sunday, October 28, 2018 12:17:41 PM MDT Neia Neutuladh via Digitalmars- d-learn wrote: > On Sun, 28 Oct 2018 18:00:06 +0000, Stanislav Blinov wrote: > > On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote: > >> and object.opEquals(a,b) do not inherits safety from class C > >> properties, and also I can't override it. > > > > Yep. Since Object is the base class and it defines opEquals as: > > ``` > > bool opEquals(Object); > > ``` > > > > the compiler rewrites `a == b` as > > `(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a @system > > call into your code. > > More pedantically, it rewrites it as: > > (a is b) || > (a !is null && (cast(Object)a).opEquals(cast(Object)b)) > > An object might not be equal to itself via opEquals, but it will always > compare equal to itself with ==.
Technically, it calls the free function opEquals in object.d, which does more than that (including introduce a hack to work around the type system to allow comparing const objects). Specifically, the current implementation is bool opEquals(Object lhs, Object rhs) { // If aliased to the same object or both null => equal if (lhs is rhs) return true; // If either is null => non-equal if (lhs is null || rhs is null) return false; // If same exact type => one call to method opEquals if (typeid(lhs) is typeid(rhs) || !__ctfe && typeid(lhs).opEquals(typeid(rhs))) /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't (issue 7147). But CTFE also guarantees that equal TypeInfos are always identical. So, no opEquals needed during CTFE. */ { return lhs.opEquals(rhs); } // General case => symmetric calls to method opEquals return lhs.opEquals(rhs) && rhs.opEquals(lhs); } /************************ * Returns true if lhs and rhs are equal. */ bool opEquals(const Object lhs, const Object rhs) { // A hack for the moment. return opEquals(cast()lhs, cast()rhs); } - Jonathan M Davis