Reputation: 1978
I have some generic template for multiton or objects pool.
public class A<TC> where TC : class, new()
{
protected static ConcurrentDictionary<object, TC> _instances = new ConcurrentDictionary<object, TC>();
public static TC Instance(object key)
{
return _instances.GetOrAdd(key, k => new TC());
}
}
// One level inheritance works as expected
public class B : A<B>
{
public virtual int Demo() { return 1; }
}
// Class C is example of what I want
// How to override method from B, pass C to A and use it in GetInstance?
public class C : B<C>
{
public override int Demo() { return 2; }
}
Question : I want class C to override method from B, how can I pass type parameter "C" through the chain of child classes to use it with method Instance() from A, is it possible at all?
I tried to modify B but seems that it makes it generic and does not allow to instantiate B :
public class B<TC> : A<TC> where TC : class, new()
{
public virtual int Demo() { return 1; }
}
Update : the idea is to have generic static constructor, then I derive class Memory from it that works with memory mapped files, but this class can read and write only bytes sequence in and out, thus, I create class MemoryStructs derived from Memory and this class can read and write whole structures, of course, I can put all these methods into Memory but I thought it may be useful to split them logically, thus, I have such inheritance chain : BaseClass > Memory > MemoryStructs
Memory and MemoryStructs classes have method OpenMemory and CloseMemory and I'm not willing to duplicate those methods for each of them, thus I need either :
Upvotes: 2
Views: 1071
Reputation: 5147
Maybe you need another class in the chain?
public class B1<T> : A<B1<T>>
{
public virtual int Demo() { return 1; }
}
public class B2 : B1<B2>
{
// Something that C does not do
}
public class C : B1<C>
{
public override int Demo() { return 2; }
}
Edit:
Seems like that you want to inherit some functionality of B and pass a type argument to it in C meanwhile you want to define B as a non-generic class, that's not possible, B must be either non-generic that you don't have C : B<C> anymore:
public class B : A<B>
{
public virtual int Demo() { return 1; }
}
public class C : B
{
public override int Demo() { return 2; }
}
or it must be generic so you can't pass B as a type argument to A:
public class B<T> : A<T>
{
public virtual int Demo() { return 1; }
}
public class C : B<T>
{
public override int Demo() { return 2; }
}
or you may choose to use the composition pattern and create an instance of B in C so that you can use it's functionality in C:
public class B : A<B>
{
public virtual int Demo() { return 1; }
}
public class C : A<C>
{
private B b = new B();
public override int Demo() {
// Maybe use b here
return 2;
}
}
Upvotes: 1
Reputation: 8404
@David Amo is absolutely correct. Maybe this is what you are after?
public abstract class A<TC> where TC : class, new()
{
protected static ConcurrentDictionary<object, TC> _instances =
new ConcurrentDictionary<object, TC>();
public static TC Instance(object key)
{
return _instances.GetOrAdd(key, k => new TC());
}
public abstract int Demo();
}
public class B : A<B>
{
public override int Demo() { return 1; }
}
public class C : A<C>
{
public override int Demo() { return 2; }
}
Upvotes: 1
Reputation: 387915
Instance
is a static method of A<TC>
so there does not even exist an Instance
method in B
which you could override (even if you could, the TC
type parameter would be bound to B
by then, so a method returning C
would be a different method).
So the way you call Instance
is using A<TC>.Instance(key)
where TC
is an actual type. So for example:
B objectB = A<B>.Instance(key)
C objectC = A<C>.Instance(key)
Note that the concurrent dictionary is separate for each type parameter TC
, so A<B>
and A<C>
do not share the same dictionary; they are different types with separate static members.
Upvotes: 2