Ian*_*Ian 7 c# generics inheritance
在尝试实现允许继承并希望有人可以提供帮助的库时,我正在努力解决一些通用约束问题.
我正在尝试建立一个有三种口味的类库,每个库都建立在另一个之上.对我来说,这似乎是一个使用泛型的绝佳机会,因为我不能通过纯粹的继承做我想做的事.下面的代码(这应该直接粘贴到VS)后面有一些解释:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
#region Base Classes
public class GenericElement { }
/// <summary>Visit to a GenericElement</summary>
public class Generic_Visit<E> where E : GenericElement
{
public E Element { get; set; }
}
/// <summary>Collection of Visits</summary>
public class Generic_Route<V, E>
where V : Generic_Visit<E>
where E : GenericElement
{
public List<V> Visits { get; set; }
public Double Distance { get; set; }
}
/// <summary>Collection of Routes</summary>
public class Generic_Solution<R, V, E>
where R : Generic_Route<V, E>
where V : Generic_Visit<E>
where E : GenericElement
{
public List<R> Routes { get; set; }
public Double Distance
{
get
{
return this.Routes.Select(r => r.Distance).Sum();
}
}
}
#endregion
#region TSP Classes
public class Concrete_TSPNode : GenericElement { }
public abstract class Generic_TSPVisit<E> : Generic_Visit<E>
where E : Concrete_TSPNode
{
public Double Time { get; set; }
}
public abstract class Generic_TSPRoute<V, E> : Generic_Route<V, E>
where V : Concrete_TSPVisit
where E : Concrete_TSPNode
{
public Double Time
{
get
{
return this.Visits.Select(v => v.Time).Sum();
}
}
}
public abstract class Generic_TSPSolution<R, V, E> : Generic_Solution<R, V, E>
where R : Concrete_TSPRoute
where V : Concrete_TSPVisit
where E : Concrete_TSPNode
{
public Double Time
{
get
{
return this.Routes.Select(r => r.Time).Sum();
}
}
}
public class Concrete_TSPVisit : Generic_TSPVisit<Concrete_TSPNode> { }
public class Concrete_TSPRoute : Generic_TSPRoute<Concrete_TSPVisit, Concrete_TSPNode> { }
public class Concrete_TSPSolution : Generic_TSPSolution<Concrete_TSPRoute, Concrete_TSPVisit, Concrete_TSPNode> { }
#endregion
#region VRP
public class Concrete_VRPNode : Concrete_TSPNode { }
public abstract class Generic_VRPVisit<E> : Generic_TSPVisit<E> where E : Concrete_VRPNode
{
public Double Capacity { get; set; }
}
public abstract class Generic_VRPRoute<V, E> : Generic_TSPRoute<V, E>
where V : Concrete_VRPVisit
where E : Concrete_VRPNode
{
public Double Capacity
{
get
{
return this.Visits.Select(v => v.Capacity).Sum();
}
}
}
public abstract class G_VRPSolution<R, V, E> : Generic_TSPSolution<R, V, E>
where R : Concrete_VRPRoute
where V : Concrete_VRPVisit
where E : Concrete_VRPNode
{
public Double Capacity
{
get
{
return this.Routes.Select(r => r.Capacity).Sum();
}
}
}
public class Concrete_VRPVisit : Generic_VRPVisit<Concrete_VRPNode> { }
public class Concrete_VRPRoute : Generic_VRPRoute<Concrete_VRPVisit, Concrete_VRPNode> { }
public class Concrete_VRPSolution : Generic_TSPSolution<Concrete_VRPRoute, Concrete_VRPVisit, Concrete_VRPNode> { }
#endregion
}
Run Code Online (Sandbox Code Playgroud)
代码背后的想法是有一组基类使用泛型公开属性.这允许我拥有强类型集合.
这三个阶段中有2个基于这些,TSP和VRP在这个例子中有4个具体的类(这些是使用类库的开发人员应该与之交互,因为通用约束只是有点疯狂) - 元素,参观,路线和解决方案.
对于TSP和VRP,还有一些前缀为Generic的类.这些允许我想要的继承,因为它暴露了通用类型.如果我不使用这些(比如Concrete_VRPRoute继承Concrete_TSPRoute),那么我必须继续强制转换Visits集合返回的项目类型以获取Capacity属性.
我相当自信所有类型都正确排列,但是当我尝试构建时,我得到以下错误,我真的不知道如何解决它们.
错误1类型"V"不能用作泛型类型或方法"Test.Generic_Route"中的类型参数"V".没有从'V'到'Test.Generic_Visit'的隐式引用转换.
错误2类型"V"不能用作泛型类型或方法"Test.Generic_Solution"中的类型参数"V".没有从'V'到'Test.Generic_Visit'的隐式引用转换.
错误3类型"R"不能用作泛型类型或方法"Test.Generic_Solution"中的类型参数"R".没有从'R'到'Test.Generic_Route'的隐式引用转换
错误4类型"V"不能用作泛型类型或方法"Test.Generic_TSPRoute"中的类型参数"V".没有从'V'到'Test.Concrete_TSPVisit'的隐式引用转换.
错误5类型"V"不能用作泛型类型或方法"Test.Generic_TSPSolution"中的类型参数"V".没有从'V'到'Test.Concrete_TSPVisit'的隐式引用转换.
错误6类型"R"不能在泛型类型或方法"Test.Generic_TSPSolution"中用作类型参数"R".没有从'R'到'Test.Concrete_TSPRoute'的隐式引用转换.
错误7类型'Test.Concrete_VRPVisit'不能在泛型类型或方法'Test.Generic_TSPSolution'中用作类型参数'V'.没有从'Test.Concrete_VRPVisit'到'Test.Concrete_TSPVisit'的隐式引用转换.
错误8"Test.Concrete_VRPRoute"类型不能在泛型类型或方法"Test.Generic_TSPSolution"中用作类型参数"R".没有从'Test.Concrete_VRPRoute'到'Test.Concrete_TSPRoute'的隐式引用转换.'Test.Concrete_TSPRoute'.
这是一块通用蛋糕.您需要根据自己定义泛型类.递归通用定义.
基础类:
public class Generic_Element<E>
where E : Generic_Element<E>
{
}
/// <summary>Visit to a Generic_Element</summary>
public class Generic_Visit<V, E>
where V : Generic_Visit<V, E>
where E : Generic_Element<E>
{
public E Element { get; set; }
}
/// <summary>Collection of Visits</summary>
public class Generic_Route<R, V, E>
where R : Generic_Route<R, V, E>
where V : Generic_Visit<V, E>
where E : Generic_Element<E>
{
public List<V> Visits { get; set; }
public Double Distance { get; set; }
}
/// <summary>Collection of Routes</summary>
public class Generic_Solution<S, R, V, E>
where S : Generic_Solution<S, R, V, E>
where R : Generic_Route<R, V, E>
where V : Generic_Visit<V, E>
where E : Generic_Element<E>
{
public List<R> Routes { get; set; }
public Double Distance
{
get
{
return this.Routes.Select(r => r.Distance).Sum();
}
}
}
Run Code Online (Sandbox Code Playgroud)
TSP课程:
public class Generic_Tsp_Element<E> : Generic_Element<E>
where E : Generic_Tsp_Element<E>
{
}
/// <summary>Visit to a Generic_Element</summary>
public class Generic_Tsp_Visit<V, E> : Generic_Visit<V, E>
where V : Generic_Tsp_Visit<V, E>
where E : Generic_Tsp_Element<E>
{
public Double Time { get; set; }
}
/// <summary>Collection of Visits</summary>
public class Generic_Tsp_Route<R, V, E> : Generic_Route<R, V, E>
where R : Generic_Tsp_Route<R, V, E>
where V : Generic_Tsp_Visit<V, E>
where E : Generic_Tsp_Element<E>
{
public Double Time
{
get
{
return this.Visits.Select(v => v.Time).Sum();
}
}
}
/// <summary>Collection of Routes</summary>
public class Generic_Tsp_Solution<S, R, V, E> : Generic_Solution<S, R, V, E>
where S : Generic_Tsp_Solution<S, R, V, E>
where R : Generic_Tsp_Route<R, V, E>
where V : Generic_Tsp_Visit<V, E>
where E : Generic_Tsp_Element<E>
{
public Double Time
{
get
{
return this.Routes.Select(r => r.Time).Sum();
}
}
}
public class Concrete_Tsp_Element : Generic_Tsp_Element<Concrete_Tsp_Element> { }
public class Concrete_Tsp_Visit : Generic_Tsp_Visit<Concrete_Tsp_Visit, Concrete_Tsp_Element> { }
public class Concrete_Tsp_Route : Generic_Tsp_Route<Concrete_Tsp_Route, Concrete_Tsp_Visit, Concrete_Tsp_Element> { }
public class Concrete_Tsp_Solution : Generic_Tsp_Solution<Concrete_Tsp_Solution, Concrete_Tsp_Route, Concrete_Tsp_Visit, Concrete_Tsp_Element> { }
Run Code Online (Sandbox Code Playgroud)
VRP课程:
public class Generic_Vrp_Element<E> : Generic_Element<E>
where E : Generic_Vrp_Element<E>
{
}
/// <summary>Visit to a Generic_Element</summary>
public class Generic_Vrp_Visit<V, E> : Generic_Visit<V, E>
where V : Generic_Vrp_Visit<V, E>
where E : Generic_Vrp_Element<E>
{
public Double Capacity { get; set; }
}
/// <summary>Collection of Visits</summary>
public class Generic_Vrp_Route<R, V, E> : Generic_Route<R, V, E>
where R : Generic_Vrp_Route<R, V, E>
where V : Generic_Vrp_Visit<V, E>
where E : Generic_Vrp_Element<E>
{
public Double Capacity
{
get
{
return this.Visits.Select(v => v.Capacity).Sum();
}
}
}
/// <summary>Collection of Routes</summary>
public class Generic_Vrp_Solution<S, R, V, E> : Generic_Solution<S, R, V, E>
where S : Generic_Vrp_Solution<S, R, V, E>
where R : Generic_Vrp_Route<R, V, E>
where V : Generic_Vrp_Visit<V, E>
where E : Generic_Vrp_Element<E>
{
public Double Capacity
{
get
{
return this.Routes.Select(r => r.Capacity).Sum();
}
}
}
public class Concrete_Vrp_Element : Generic_Vrp_Element<Concrete_Vrp_Element> { }
public class Concrete_Vrp_Visit : Generic_Vrp_Visit<Concrete_Vrp_Visit, Concrete_Vrp_Element> { }
public class Concrete_Vrp_Route : Generic_Vrp_Route<Concrete_Vrp_Route, Concrete_Vrp_Visit, Concrete_Vrp_Element> { }
public class Concrete_Vrp_Solution : Generic_Vrp_Solution<Concrete_Vrp_Solution, Concrete_Vrp_Route, Concrete_Vrp_Visit, Concrete_Vrp_Element> { }
Run Code Online (Sandbox Code Playgroud)
最终结果是非通用的具体类,可以像这样使用:
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<Concrete_Tsp_Visit>(new[] { v });
r.Distance = 2.1;
var s = new Concrete_Tsp_Solution();
s.Routes = new List<Concrete_Tsp_Route>(new[] { r });
Console.WriteLine(s.Distance);
Console.WriteLine(s.Time);
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
请享用!请享用!