Skip to content

Instantly share code, notes, and snippets.

@daiplusplus
Created May 26, 2020 06:15
Show Gist options
  • Save daiplusplus/277ca517a7bbdc66784f13481cb1f6e1 to your computer and use it in GitHub Desktop.
Save daiplusplus/277ca517a7bbdc66784f13481cb1f6e1 to your computer and use it in GitHub Desktop.
Subclasses can reimplement interfaces to effectively override non-virtual methods
void Main()
{
BaseClass b = new BaseClass();
DerivedClass d = new DerivedClass();
ReimplementedDerivedClass r = new ReimplementedDerivedClass();
//
b.GetX().Dump( b.GetType().Name ); // "1"
d.GetX().Dump( d.GetType().Name ); // "2"
r.GetX().Dump( r.GetType().Name ); // "2"
//
IFoo bFoo = b;
bFoo.GetX().Dump( b.GetType().Name + " as IFoo" ); // "1"
IFoo d1Foo = d;
d1Foo.GetX().Dump( d.GetType().Name + " as IFoo"); // "1"
IFoo d2Foo = r;
d2Foo.GetX().Dump(r.GetType().Name + " as IFoo"); // "2" <-- okay, THIS output surprised me!
//
BaseClass dAsBase = d; // I assumed that casting to a baseclass would "reset" the vtable pointer...
BaseClass rAsBase = r;
dAsBase.GetX().Dump( dAsBase.GetType().Name ); // "1" // non-virtual call
rAsBase.GetX().Dump( rAsBase.GetType().Name ); // "1" // non-virtual call
IFoo dAsBaseFoo = dAsBase;
dAsBaseFoo.GetX().Dump( dAsBaseFoo.GetType().Name + " as IFoo" ); // "1" // DerivedClass's IFoo.GetX() is in BaseClass
IFoo rAsBaseFoo = rAsBase;
rAsBaseFoo.GetX().Dump(rAsBaseFoo.GetType().Name + " as IFoo"); // "2" // ReimplementedDerivedClass's IFoo.GetX() is in ReimplementedDerivedClass.
}
interface IFoo {
Int32 GetX();
}
class BaseClass : IFoo {
public Int32 GetX() => 1;
}
class DerivedClass : BaseClass
{
public new Int32 GetX() => 2;
}
class ReimplementedDerivedClass : BaseClass, IFoo // <-- reimplements IFoo, even though `GetX` isn't virtual and is actually `new`.
{
public new Int32 GetX() => 2;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment