I thought about this some more and you can make the fakery even better, as long as you can actually inherit from A and B (which is a requirement for multiple inheritance when it's supported, obviously):
class Multi { // : A, B
private A a;
private B b;
Multi(string argForA, int argForB){
a = new HostedA(this, argForA);
b = new HostedB(this, argForB);
}
public static implicit operator A(Multi m) { return m.a; }
public static implicit operator B(Multi m) { return m.b; }
public static implicit operator Multi(A a) { return ((HostedA)a).host; }
public static implicit operator Multi(B b) { return ((HostedB)b).host; }
private class HostedA : A {
internal Multi host;
internal HostedA(Multi host, string argsForA) : base(argsForA) {
this.host = host;
}
}
private class HostedB : B {
internal Multi host;
internal HostedB(Multi host, int argsForB) : base(argsForB) {
this.host = host;
}
}
}
Those cast-back operators will fail if you give it the wrong sort of A or B (i.e. one that isn't a cast-out of a Multi), but that's correct (though the exception message might not be quite right). You can override behaviour 'inherited' from A and B in HostedA and HostedB, and as inner classes they have access to their host's private state and methods. If you want Multi itself to be virtual and inheritable, you can virtualise the creation of the instances of A and B and make the hosted classes visible for inheritance:
class Multi { // : A, B
private A a;
private B b;
Multi(string argForA, int argForB){
a = ConstructA();
b = ConstructB();
}
protected virtual HostedA ConstructA(string argForA) { return new HostedA(this, argForA); }
protected virtual HostedB ConstructB(int argForB) { return new HostedB(this, argForB); }
public static implicit operator A(Multi m) { return m.a; }
public static implicit operator B(Multi m) { return m.b; }
public static implicit operator Multi(A a) { return ((HostedA)a).Host; }
public static implicit operator Multi(B b) { return ((HostedB)b).Host; }
protected class HostedA : A {
public Multi Host { get; private set; }
public HostedA(Multi host, string argsForA) : base(argsForA) {
this.Host = host;
}
}
protected class HostedB : B {
public Multi Host { get; private set; }
public HostedB(Multi host, int argsForB) : base(argsForB) {
this.Host = host;
}
}
}
To override some of Multi's 'A' behaviour, create a new inner subclass and overrid