I have the following generic interface:
public interface IContainer<T>
and a generic interface that acts as a container for these generic interfaces:
public interface IGroupOfContainers<TContainer, TValue>
where TContainer : IContainer<TValue>
Now I can define some classes:
public class SomeContainer<T> : IContainer<T>
...
public class OtherContainer<T> : IContainer<T>
...
public class SomeGroupOfContainers<TContainer, TValue>
: IGroupOfContainers<TContainer, TValue>
where TContainer : IContainer<TValue>
...
public class OtherGroupOfContainers<TContainer, TValue>
: IGroupOfContainers<TContainer, TValue>
where TContainer : IContainer<TValue>
...
Now I want IntGroupManager to be able to work with any object that complies with the IGroupOfContainers<IContainer<int>, int> interface:
public class IntGroupManager
{
public IGroupOfContainers<IContainer<int>, int> IntGroup { get; set; }
...
}
But when I try:
var manager= new IntGroupManager();
manager.IntGroup = new GroupOfContainers<Container<int>, int>
as IGroupOfContainers<IContainer<int>, int>;
I get a "Suspicious cast: there is no type which is inherited from both GroupOfContainers<Container<int>, int> and IGroupOfContainers<IContainer<int>, int>" warning, and when I attempt to run the code, manager.IntGroup is set to null, as the cast failed.
If I change the type signature of the IntGroup property to
public IGroupOfContainers<Container<int>, int> IntGroup { get; set; }
(changing IContainer to the concrete class Container), the code executes properly. However, I then wouldn't be able to instantiate an instance of IntGroupManager with an IntGroup of type, say, GroupOfContainers<OtherContainer<int>, int>, since OtherContainer is not derived from Container.
I could introduce generic parameters into the definition of IntGroupManager, perhaps rewriting it as
public class IntGroupManager<TContainer> where TContainer : IContainer<int>
However, this would bind any instance of IntGroupManager to a specific type of IContainer; I wouldn't be able to do
var manager = new IntGroupManager<Container<int>>();
// Set manager.IntGroup and do some things with it
// This is okay
manager.IntGroup = new GroupOfContainers<Container<int>, int>();
// manager executes some code involving IntGroup and manipulates its internal state
// Set manager.IntGroup to something else and do things with it
// This is not okay, since OtherContainer<int> is not derived from Container<int>
manager.IntGroup = new GroupOfContainers<OtherContainer<int>, int>();
and so I lose some flexibility.
How can I properly define the IntGroup property to be of any type conforming to IGroupOfContainers<IContainer<int>, int>? I want to be able to use the same instance of IntGroupManager with any IntGroup object that conforms to IGroupOfContainers<IContainer<int>, int>. Is there a way to do this?