I'm trying to provide a base class for a UI API to provide a Tab control. It's in C#.NET (4.5) but not using WinForms.
I have the tab control working perfectly, but a requirement has come up to have various customised tabs and pages, both in appearance and functionality, and rather than clone large chunks of code for each, I'm trying to provide a generic base class that you give a TTab
and TPage
type to.
The idea is in the API I can then provide classes which simply wrap the generic base into a non-generic class to actually use: DefaultTabs : BaseTabs<DefaultTab, DefaultTabPage>
I wasn't expecting this to be particularly troublesome, but I've managed to get all confused along the way, and I'm pretty sure I'm starting to go codeblind to the problem.
Here's a boiled down version:
namespace ExtendTabs.soExample
{
using System.Collections.Generic;
public class Example<TTab, TPage>
where TTab : Tab<TPage>, new()
where TPage : TabPage<TTab>, new()
{
private List<TTab> tabs;
public Example()
{
this.tabs = new List<TTab>();
this.tabs.Add(new TTab());
}
}
public class Tab<TPage>
where TPage : new() // where TPage : TabPage<..? All I can think of is "TabPage<Tab<TPage>>" and that seems very wrong.
{
public Tab()
{
this.Page = new TPage(); // Can't pass this in because of the where new() constraint.
//this.Page.Tab = this; // Can't do this because TPage does not contain where
//this.Page.Link(this); // Can't do this because TPage does not contain where
}
public TPage Page { get; private set; }
}
public class TabPage<TTab>
{
public TabPage() // Can't take in Tab<TPage> here because of type problems and new() constrain used.
{
}
public TTab Tab { get; internal set; }
internal void Link(TTab tab)
{
this.Tab = tab;
}
}
}
The 2 main problems are:
It doesn't compile on the main class line, with(Thanks Siva)'TPage' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TPage' in the generic type or method 'ExtendTabs.soExample.Tab<TPage>'
. I don't understand this error as TPage does have a public paramterless constructor and is non-abstract.I can't seem to add the
TTab
instance to theTPage
instance without ending up with some sort of recursive generic type hell.
I'm hoping I've just been looking at this for too long and am trying to make this problem far too complicated. It seems like it should be a lot easier than this really. Any suggestions?
The first problem stemmed from the main class not including the same generic constraint as the subclass. As per the link Siva provided, I've now added the new()
constraint and fixed that error.