the topic is not really related to generics or interfaces.
say you class foo, and you want to implement a common method bar(), you have two choices. inheritance and composition (wrapping).
// common method to implement
public interface IBar
{
string Bar();
}
// base class that implements Bar()
public class BaseBar : IBar
{
public string Bar() { return "bar";}
}
// add the Bar method via inhertiemce
public class Foo1 : BaseBar
{
}
// some class without Bar() method
public class Foo
{
public string ID = "Foo";
}
// add the bar method to Foo class via composition
public class BarAdder : IBar
{
private Foo foo;
public BarAdder (Foo foo)
{
this.foo = foo;
}
public Foo Foo => foo;
public string Bar() { return "AddedBar to " + foo.ID; }
}
public void Test()
{
var foo1 = new Foo1();
foo1.Bar();
var foo = new Foo();
var foo2 = new BarAdder(foo);
foo2.Bar();
foo2.Foo.ID;
}
you can see BarAdder would be more useful as a generic because it could add the Bar() to any class that implemented the ID property. Typically you would make the ID property an interface. the the wrapper class could add the Bar() method to any class that implemented ID interface. That is what your sample code did.
hopefully you already understand interface design, and why interfaces are used instead of inheritance.
the issue with inheritance is with virtual methods. if the class hierarchy gets deep, it easy so make a breaking change to a inherited method. a wrapper class avoids this.