Generic Classes and Heirarchy Classes

Ronald Rex 1,666 Reputation points
2023-09-24T23:42:30.3033333+00:00

Hi Friends. I am learning how to consume Generics, but I was wondering if I could get some assistance concerning what are Hierarchy Classes and Wrapper Classes and the purpose for them. I have included some code that was shared with me during a tutorial session that utilizes a Hierarchy Class and Wrapper Class, but I dont understand what the code is accomplishing doing. Thanks !!!

namespace GenericSample;

public interface IIdentifiable
{
    public int Id { get; set; }
}

public class Employee : IIdentifiable
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;

    public Employee(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

public class Room : IIdentifiable
{
    public int Id { get; set; }
    public int Capacity { get; set; } = 0;

    public Room(int id, int capacity)
    {
        Id = id;
        Capacity = capacity;
    }
}

public class HierarchyWrapper<T>
    where T : IIdentifiable // type constraint
{
    public T Value { get; set; }
    public HierarchyWrapper<T> Superior { get; set; } = null!;

    public HierarchyWrapper(T value)
    {
        Value = value;
    }

    public override string ToString()
    {
        return Value.Id.ToString();
    }
}

Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 78,006 Reputation points Volunteer Moderator
    2023-09-25T16:06:32.0266667+00:00

    the topic is not really related to generics or interfaces.

    say you class foo, and you want to implement a common method bar(), you have two choices. inheritance and composition (wrapping).

    // common method to implement
    public interface IBar
    {
       string Bar();
    }
    
    // base class that implements Bar()
    public class BaseBar : IBar
    {
        public string Bar() { return "bar";}
    }
    
    // add the Bar method via inhertiemce
    public class Foo1 : BaseBar
    {
    }
    
    // some class without Bar() method 
    public class Foo 
    {
        public string ID = "Foo";
    }
    
    // add the bar method to Foo class via composition 
    public class BarAdder : IBar
    {
        private Foo foo;
        public BarAdder (Foo foo) 
        {
            this.foo = foo;
        }
        public Foo Foo => foo; 
        public string Bar() { return "AddedBar to " + foo.ID; }
    
    }
    
    public void Test()
    {
       var foo1 = new Foo1();
       foo1.Bar();
    
       var foo = new Foo();
       var foo2 = new BarAdder(foo);
       foo2.Bar(); 
       foo2.Foo.ID;
    }
    
    

    you can see BarAdder would be more useful as a generic because it could add the Bar() to any class that implemented the ID property. Typically you would make the ID property an interface. the the wrapper class could add the Bar() method to any class that implemented ID interface. That is what your sample code did.

    hopefully you already understand interface design, and why interfaces are used instead of inheritance.

    the issue with inheritance is with virtual methods. if the class hierarchy gets deep, it easy so make a breaking change to a inherited method. a wrapper class avoids this.


1 additional answer

Sort by: Most helpful
  1. Anonymous
    2023-09-25T05:25:17.5266667+00:00

    Hi @Ronald Rex , Welcome to Microsoft Q&A,

    In your code, "HierarchyWrapper<T>" is a generic class where "T" is the type parameter. This means you can create a "HierarchyWrapper" instance for any type that implements the "IIdentABLE" interface.

    IIdentificable is an interface that specifies the contract of an object with an integer Id property. Both the Employee and Room classes implement this interface, which means they must provide an implementation for the Id property.

    Employee and Room are concrete classes that represent entities with an Id property and other properties specific to each entity.

    HierarchyWrapper<T> is a wrapper class that takes any object of type T that implements the IIdentABLE interface.

    It has two properties:

    • Value: This property holds the actual object of type T.
    • Superior: This property represents a reference to a superior (parent) object in the hierarchy. It is

    initialized to null!, indicating that it can be null.

    • The constructor of "HierarchyWrapper" takes an object of type "T" and assigns it to the "Value" property.
    • Override the "ToString" method to return the "Id" of the "Value" property as a string.

    You appear to be creating a hierarchy of objects where each "HierarchyWrapper<T>" object can reference a parent object of the same type ("Superior"). You can use these wrappers to build hierarchies with different types of objects such as employees and rooms, as long as they implement the "IIdentABLE" interface.

    For example, you can create a hierarchy like this:

    class Program
    {
        static void Main(string[] args)
        {
            var employee1 = new Employee(1, "a");
            var employee2 = new Employee(2, "b");
            var employee3 = new Employee(3, "c");
    
            var wrapper1 = new HierarchyWrapper<Employee>(employee1);
            var wrapper2 = new HierarchyWrapper<Employee>(employee2);
            var wrapper3 = new HierarchyWrapper<Employee>(employee3);
    
            // Creating a hierarchy of employees
            wrapper1.Superior = wrapper3; // a reports to c
            wrapper2.Superior = wrapper3; // b also reports to c
        }
    }
    

    You can check out the Composite Pattern and Decorator Pattern in design patterns.

    Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.