1

I have 2 generic classes: a ManagerBase class and a ChildBase class. They're both abstract and are intended to be made concrete. ManagerBase has a list of ChildBase, which is why I want to make it generic, so a CatalogManager : ManagerBase would have a list of Catalogs. Also, each Catalog would have reference to its' Manager - CatalogManager.

public class ManagerBase<T1> : ChildBase<???>
{
    public ManagerBase()
    {
        ChildObjects = new List<T1>();
    }

    public List<T1> ChildObjects { get; set; }
}

public class ChildBase<T1> : ManagerBase<???>
{
    public ChildBase(T1 parentMgr)
    {
        ParentMgr = parentMgr;
        ParentMgr.ChildObjects.Add(this);
    }

    public T1 ParentMgr { get; set; }
}

How can I resolve this object model?

Thanks.

1
  • public class ManagerBase<TManager, TChild> where TManager : ManagerBase<TManager, TChild> where TChild : ChildBase<TManager, TChild>, public class ChildBase<TManager, TChild> where TManager : ManagerBase<TManager, TChild> where TChild : ChildBase<TManager, TChild>, class CatalogManager : ManagerBase<CatalogManager, Catalog>, class Catalog : ChildBase<CatalogManager, Catalog>. Commented Apr 9, 2017 at 20:04

1 Answer 1

1

You have to define the base classes using the "curiously recursive" pattern:

public class ManagerBase<M, T1>
    where M : ManagerBase<M, T1>
    where T1 : ChildBase<M, T1>
{
    public ManagerBase()
    {
        ChildObjects = new List<T1>();
    }

    public List<T1> ChildObjects { get; set; }
}

public class ChildBase<T1, C>
    where T1 : ManagerBase<T1, C>
    where C : ChildBase<T1, C>
{
    public ChildBase(T1 parentMgr)
    {
        ParentMgr = parentMgr;
        ParentMgr.ChildObjects.Add((C)(object)this);
    }

    public T1 ParentMgr { get; set; }
}

Please note I've stuck with your usage of T1, but I think that's a bit confusing. I would have preferred to have used M and C for each.

The major downside with this is that you have to use the nasty double cast of (C)(object)this to make this work. C# doesn't allow full type safety on this pattern. A nefarious developer can create child classes that can break the pattern.

Then the concrete classes can be this:

public class CatalogManager : ManagerBase<CatalogManager, Catalog>
{
}

public class Catalog : ChildBase<CatalogManager, Catalog>
{
    public Catalog(CatalogManager parentMgr) : base(parentMgr)
    {
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.