我正在试图弄清楚是否有更好的方法来构建一些代码。虽然它目前有效,但它总是让我感到困惑,因为它具有仿制限制所带来的复杂性和疯狂性。我有兴趣知道是否有人想要更整洁的解决方案。
我已经包含了一个类图,使事情变得更容易一些。
这一切都在图书馆内进行,我想尽可能保持我所有类型的安全。该库有3层不断增加的复杂性。我稍后会解释一下。
我正在使用Generics来使所有类型都有效。例如,路线实际上是List<T>
,其中T
是访问。现在因为我有3层,我希望能够从Route本身访问这些Visits(以及它们对应的节点)的属性(并使其更容易使用)。所以这实际上是Route<Visit<Node>>
。将其添加到需要强类型Solution<Route<Visit<Node>>>
的解决方案后,事情会变得复杂。
这会产生一些不太明显的代码:
public abstract class Solution<TSolution, TRoute, TVisit, TNode, TResource>
where TSolution : Solution<TSolution, TRoute, TVisit, TNode, TResource>, new()
where TRoute : Route<TRoute, TVisit, TNode, TResource>, new()
where TVisit : Visit<TVisit, TNode>, new()
where TNode : Element<TNode>
where TResource : Resource<TResource>
一切都很好,但我必须在每个类/级别定义这些约束。在每个复杂程度,我创建一些简单的消耗类,如下所示,基本上隐藏了无法使用的通用约束。
Level1.Solution : Common.Solution<Solution, Route, Visit, Node, Resource>
他们也根据这个question的建议进行了递归,以允许我扩展课程。例如,Level2.Solution将需要能够将Level2.Route指定为约束之一,通常在没有递归的情况下这将不起作用(co / contra方差和泛型)。
总而言之,它起作用,但至少可以说有点狡猾。任何人都有任何想法如何可以很好地重新工作?
答案 0 :(得分:2)
路线实际上是一个列表
如果您prefer composition over inheritance,我认为您的代码会大大简化。如果Route 有列表,它将变得更简单,更容易管理。
答案 1 :(得分:1)
我认为这里的问题是你尝试将它们组合在一个地方。例如,您不必告诉任何有关节点及其合同的解决方案,但在您的情况下,您可以这样做。尝试使用接口而不是通用约束 - 您仍然可以从资源和节点组合的不同路由创建解决方案,但最终您只需要指定具体的解决方案:
interface INode {}
class Node: INode {}
interface IVisit
class Visit: IVisit
{
Visit(INode node) {}
}
interface ISolution {}
class Solution: ISolution
{
Solution(IList<IRoute> routes)
{
}
}
答案 2 :(得分:1)
我承认我可能会遗漏一些东西,但看着这个问题和你的相关问题,我觉得这太复杂了。看起来syntaxophilia的情况变得疯狂了。当我遇到类似这样的事情时,通常需要坐下来思考我用简单的术语建模的东西。
据我了解,这些通用约束只是确保类型在Resource
,Node
,Visit
,Route
和{{1}之间兼容}类型参数。一切都很好,如果非常复杂的话。唯一的“变量”是您的Solution
和TResource
类型。我的意思是,你可以:
类解决方案 其中TNode:元素 其中TResource:资源 { //根据需要构建“访问和路由”的属性 }
您的示例表明VSPSolution始终具有VSPVisit和VSPRoute。如果是这种情况,那么这里的组合解决方案大大简化了事情。事实上,如果我更了解TNode
和TNode
的目的,您也可以消除这些通用约束。
真正的问题是TResource
(或Visit
)对象是否必须存在于Route
之外。它看起来像一个非常严格的层次结构:Solution
- &gt; Solution
- &gt; Route
,因此Visit
包含Solution
,Route
包含Route
集合是有意义的。
这样做会简单得多,而且更清楚的是发生了什么。