How to use Inheritance when using Generic Constraints

后端 未结 3 803
梦毁少年i
梦毁少年i 2021-02-06 07:33

I\'m struggling with some Generic constraint issues when trying to implement a library that allows inheritance and hoping someone can help.

I\'m trying to build up a cl

3条回答
  •  无人共我
    2021-02-06 08:05

    It's a piece of generic cake. You need to define the generic classes in terms of themselves. A recursive generic definition.

    Base Classes:

    public class Generic_Element
        where E : Generic_Element
    {
    }
    
    /// Visit to a Generic_Element
    public class Generic_Visit
        where V : Generic_Visit
        where E : Generic_Element
    {
        public E Element { get; set; }
    }
    
    /// Collection of Visits
    public class Generic_Route
        where R : Generic_Route
        where V : Generic_Visit
        where E : Generic_Element
    {
        public List Visits { get; set; }
        public Double Distance { get; set; }
    }
    
    /// Collection of Routes
    public class Generic_Solution
        where S : Generic_Solution
        where R : Generic_Route
        where V : Generic_Visit
        where E : Generic_Element
    {
        public List Routes { get; set; }
    
        public Double Distance
        {
            get
            {
                return this.Routes.Select(r => r.Distance).Sum();
            }
        }
    }
    

    TSP Classes:

    public class Generic_Tsp_Element : Generic_Element
    where E : Generic_Tsp_Element
    {
    }
    
    /// Visit to a Generic_Element
    public class Generic_Tsp_Visit : Generic_Visit
        where V : Generic_Tsp_Visit
        where E : Generic_Tsp_Element
    {
        public Double Time { get; set; }
    }
    
    /// Collection of Visits
    public class Generic_Tsp_Route : Generic_Route
        where R : Generic_Tsp_Route
        where V : Generic_Tsp_Visit
        where E : Generic_Tsp_Element
    {
        public Double Time
        {
            get
            {
                return this.Visits.Select(v => v.Time).Sum();
            }
        }
    }
    
    /// Collection of Routes
    public class Generic_Tsp_Solution : Generic_Solution
        where S : Generic_Tsp_Solution
        where R : Generic_Tsp_Route
        where V : Generic_Tsp_Visit
        where E : Generic_Tsp_Element
    {
        public Double Time
        {
            get
            {
                return this.Routes.Select(r => r.Time).Sum();
            }
        }
    }
    
    public class Concrete_Tsp_Element : Generic_Tsp_Element { }
    
    public class Concrete_Tsp_Visit : Generic_Tsp_Visit { }
    
    public class Concrete_Tsp_Route : Generic_Tsp_Route { }
    
    public class Concrete_Tsp_Solution : Generic_Tsp_Solution { }
    

    VRP Classes:

    public class Generic_Vrp_Element : Generic_Element
    where E : Generic_Vrp_Element
    {
    }
    
    /// Visit to a Generic_Element
    public class Generic_Vrp_Visit : Generic_Visit
        where V : Generic_Vrp_Visit
        where E : Generic_Vrp_Element
    {
        public Double Capacity { get; set; }
    }
    
    /// Collection of Visits
    public class Generic_Vrp_Route : Generic_Route
        where R : Generic_Vrp_Route
        where V : Generic_Vrp_Visit
        where E : Generic_Vrp_Element
    {
        public Double Capacity
        {
            get
            {
                return this.Visits.Select(v => v.Capacity).Sum();
            }
        }
    }
    
    /// Collection of Routes
    public class Generic_Vrp_Solution : Generic_Solution
        where S : Generic_Vrp_Solution
        where R : Generic_Vrp_Route
        where V : Generic_Vrp_Visit
        where E : Generic_Vrp_Element
    {
        public Double Capacity
        {
            get
            {
                return this.Routes.Select(r => r.Capacity).Sum();
            }
        }
    }
    
    public class Concrete_Vrp_Element : Generic_Vrp_Element { }
    
    public class Concrete_Vrp_Visit : Generic_Vrp_Visit { }
    
    public class Concrete_Vrp_Route : Generic_Vrp_Route { }
    
    public class Concrete_Vrp_Solution : Generic_Vrp_Solution { }
    

    The final result is non-generic concrete classes that can be used like this:

    var e = new Concrete_Tsp_Element();
    var v = new Concrete_Tsp_Visit();
    v.Element = e;
    v.Time = 0.5;
    var r = new Concrete_Tsp_Route();
    r.Visits = new List(new[] { v });
    r.Distance = 2.1;
    var s = new Concrete_Tsp_Solution();
    s.Routes = new List(new[] { r });
    Console.WriteLine(s.Distance);
    Console.WriteLine(s.Time);
    Console.ReadLine();
    

    Enjoy! Enjoy!

提交回复
热议问题