【发布时间】:2010-09-02 12:12:25
【问题描述】:
在尝试实现允许继承的库并希望有人能提供帮助时,我遇到了一些通用约束问题。
我正在尝试构建一个具有 3 种风格的类库,每种风格都建立在另一个之上。对我来说,这似乎是一个使用泛型的绝佳机会,因为我不能完全通过纯粹的继承来做我想做的事。代码如下(这应该直接粘贴到 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
}
代码背后的想法是有一组使用泛型公开属性的基类。例如,这允许我拥有强类型集合。
3 个阶段中有 2 个建立在这些阶段之上,示例中的 TSP 和 VRP 有 4 个具体类(这些是使用类库的开发人员应该与之交互的,因为通用约束有点疯狂) - 元素、访问、路线和解决方案。
对于 TSP 和 VRP,还有一些以 Generic 为前缀的类。这些允许我想要的继承,因为它公开了通用类型。如果我不使用这些(例如 Concrete_VRPRoute 继承 Concrete_TSPRoute),那么我必须继续转换 Visits 集合返回的项目类型以获取容量属性。
我相当有信心所有类型都正确排列,但是当我尝试构建时出现以下错误,我真的不知道如何解决它们。
错误 1 类型 'V' 不能用作 泛型类型中的类型参数“V” 或方法“Test.Generic_Route”。 没有隐式引用 从“V”转换为 'Test.Generic_Visit'。
错误 2 类型“V”不能用作类型 泛型类型中的参数“V”或 方法“Test.Generic_Solution”。 没有隐式引用 从“V”转换为 'Test.Generic_Visit'。
错误 3 类型“R”不能用作类型 泛型类型中的参数“R”或 方法“Test.Generic_Solution”。 没有隐式引用 从“R”转换为 'Test.Generic_Route'
错误 4 类型 'V' 不能用作 泛型类型中的类型参数“V” 或方法 'Test.Generic_TSPRoute'。有 没有隐式引用转换 “V”到“Test.Concrete_TSPVisit”。
错误 5 类型 'V' 不能用作 泛型类型中的类型参数“V” 或方法 'Test.Generic_TSPSolution'。 没有隐式引用 从“V”转换为 'Test.Concrete_TSPVisit'。
错误 6 类型“R”不能用作类型 泛型类型中的参数“R”或 方法 'Test.Generic_TSPSolution'。 没有隐式引用 从“R”转换为 'Test.Concrete_TSPRoute'。
错误 7 类型“Test.Concrete_VRPVisit”不能 用作类型参数“V” 泛型类型或方法 'Test.Generic_TSPSolution'。 没有隐式引用 从转换 'Test.Concrete_VRPVisit' 到 'Test.Concrete_TSPVisit'。
错误 8 类型“Test.Concrete_VRPRoute”不能 用作类型参数“R” 泛型类型或方法 'Test.Generic_TSPSolution'。 没有隐式引用 从转换 'Test.Concrete_VRPRoute' 到 'Test.Concrete_TSPRoute'。'Test.Concrete_TSPRoute'。
【问题讨论】:
标签: c# generics inheritance