Resolved Need help on nested generic collections and item

Periasamy

New member
Joined
Mar 18, 2025
Messages
3
Programming Experience
10+
I have aa requirement of Collection classes inherited at multiple levels with corresponding Item class at each level as in below example.

C#:
    public interface IOwnable<TOwner>
    {
        TOwner Owner { get; set; }
    }

    public abstract class BaseItem
    {
        // Common properties and methods for all items
    }

    public abstract class OwnableCollection<TItem, TCollection> : List<TItem>
        where TItem : BaseItem, IOwnable<TCollection>
        where TCollection : OwnableCollection<TItem, TCollection>
    {
        protected OwnableCollection()
        {
        }

        public new void Add(TItem item)
        {
            item.Owner = (TCollection)this;
            base.Add(item);
        }

        public new void AddRange(IEnumerable<TItem> items)
        {
            foreach (var item in items)
            {
                Add(item);
            }
        }
    }

    // -------------------------------------------------

    public abstract class IntermediateCollection<TItem, TCollection> : OwnableCollection<TItem, TCollection>
        where TItem : IntermediateItem<TCollection>, IOwnable<TCollection>
        where TCollection : IntermediateCollection<TItem, TCollection>
    {
        // Additional shared implementation for intermediate collections
    }

    public abstract class IntermediateItem<TOwner> : BaseItem, IOwnable<TOwner>
        where TOwner : IntermediateCollection<IntermediateItem<TOwner>, TOwner>
    {
        public TOwner Owner { get; set; }
        // Additional shared implementation for intermediate items
    }

    // -------------------------------------------------

    public class SpecificCollection : IntermediateCollection<SpecificItem, SpecificCollection>
    {
        // Specific implementation for this collection
    }

    public class SpecificItem : IntermediateItem<SpecificCollection>
    {
        // Specific implementation for this item
    }

    // -------------------------------------------------

    public abstract class MoreSpecificCollection<TItem, TCollection> : IntermediateCollection<TItem, TCollection>
        where TItem : MoreSpecificItem<TCollection>, IOwnable<TCollection>
        where TCollection : MoreSpecificCollection<TItem, TCollection>
    {
        // Additional shared implementation for more specific collections
    }

    public abstract class MoreSpecificItem<TOwner> : IntermediateItem<TOwner>
        where TOwner : IntermediateCollection<MoreSpecificItem<TOwner>, TOwner>
    {
        // Additional shared implementation for more specific items
    }

    // -------------------------------------------------

    public class VerySpecificCollection : MoreSpecificCollection<VerySpecificItem, VerySpecificCollection>
    {
        // Very specific implementation for this collection
    }

    public class VerySpecificItem : MoreSpecificItem<VerySpecificCollection>
    {
        // Very specific implementation for this item
    }

    // -------------------------------------------------

In the above, I am unsure about implicit reference conversion for TItem in IntermediateCollection<TItem, TCollection> into IntermediateItem<TCollection>.

Any help on this would be greatly appreciated.
 
It's not clear what you're actually asking. What exactly is it that you're not clear about? Are you asking why something happens? Are you asking how to do something specific? If your saying that you're not sure why you can treat a reference of type TItem as type IntermediateItem<TCollection> inside an object of type IntermediateCollection<TItem, TCollection> then your answer is right here:
C#:
    public abstract class IntermediateCollection<TItem, TCollection> : OwnableCollection<TItem, TCollection>
        where TItem : IntermediateItem<TCollection>, IOwnable<TCollection>
        where TCollection : IntermediateCollection<TItem, TCollection>
That generic constraint literally says that every reference of type TItem will be to an object that is of type IntermediateItem<TCollection> or a type that inherits it. That is exactly why generic constraints exist: to enable you to assume certain types or functionality in generic code. If you tried to create an IntermediateCollection object where TItem was not type IntermediateItem<TCollection> then the compiler would flag it as an error.

If that's not what you were asking then I have no idea what you mean and you'll need to clarify.
 
It's not clear what you're actually asking. What exactly is it that you're not clear about? Are you asking why something happens? Are you asking how to do something specific? If your saying that you're not sure why you can treat a reference of type TItem as type IntermediateItem<TCollection> inside an object of type IntermediateCollection<TItem, TCollection> then your answer is right here:
C#:
    public abstract class IntermediateCollection<TItem, TCollection> : OwnableCollection<TItem, TCollection>
        where TItem : IntermediateItem<TCollection>, IOwnable<TCollection>
        where TCollection : IntermediateCollection<TItem, TCollection>
That generic constraint literally says that every reference of type TItem will be to an object that is of type IntermediateItem<TCollection> or a type that inherits it. That is exactly why generic constraints exist: to enable you to assume certain types or functionality in generic code. If you tried to create an IntermediateCollection object where TItem was not type IntermediateItem<TCollection> then the compiler would flag it as an error.

If that's not what you were asking then I have no idea what you mean and you'll need to clarify.

Thank you very much for your response.

Actually, we are trying to implement C# generics-based implementation of collections classes with their corresponding elements classes that spans more than 5 levels of inheritance, and the elements class must implement `Owner` property is of a collection type that refers to its corresponding containing collection class. Additionally, the collection classes should contain a `Parent` property that references to one of the Element class object reference which is an element in another parent collection. so that we can have multiple collections containing their corresponding elements that would have links to the dependent child collections.

After a few attempts, we were able to find the answer.
 
Just my guess, but I think that they were trying to guarantee type safety so that the collection of Gen-X parents will only have Gen-Y children, and never be in a situation of where a Gen-Y child would also have a Gen-Y parent.

E.g. The typical generic tree implementation won't quite work:
C#:
class TreeNode<T>
{
    public T Value { get; set; }
    public TreeNode<T> Parent { get; set; }
    public List<TreeNode<T>> Children { get; } = new();
}

class BaseGen { ... }
class GenX : BaseGen { ... }
class GenY : BaseGen { ... }

:

TreeNode<BaseGen> root = ....;
 
It could be useful to others if you were to provide your solution. I will mark this thread resolved. If and when you do add a post containing the solution, please flag it as a solution, which you do by clicking the tick/check mark on the right. That makes it obvious to everyone so there's no need to read the whole thread.
 
Back
Top Bottom