重组建议删除许多通用约束

时间:2011-01-31 20:27:05

标签: c# generics refactoring

我正在试图弄清楚是否有更好的方法来构建一些代码。虽然它目前有效,但它总是让我感到困惑,因为它具有仿制限制所带来的复杂性和疯狂性。我有兴趣知道是否有人想要更整洁的解决方案。

我已经包含了一个类图,使事情变得更容易一些。 enter image description here

这一切都在图书馆内进行,我想尽可能保持我所有类型的安全。该库有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方差和泛型)。

总而言之,它起作用,但至少可以说有点狡猾。任何人都有任何想法如何可以很好地重新工作?

3 个答案:

答案 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的情况变得疯狂了。当我遇到类似这样的事情时,通常需要坐下来思考我用简单的术语建模的东西。

据我了解,这些通用约束只是确保类型在ResourceNodeVisitRoute和{{1}之间兼容}类型参数。一切都很好,如果非常复杂的话。唯一的“变量”是您的SolutionTResource类型。我的意思是,你可以:

类解决方案     其中TNode:元素     其中TResource:资源 {      //根据需要构建“访问和路由”的属性 }

您的示例表明VSPSolution始终具有VSPVisit和VSPRoute。如果是这种情况,那么这里的组合解决方案大大简化了事情。事实上,如果我更了解TNodeTNode的目的,您也可以消除这些通用约束。

真正的问题是TResource(或Visit)对象是否必须存在于Route之外。它看起来像一个非常严格的层次结构:Solution - &gt; Solution - &gt; Route,因此Visit包含SolutionRoute包含Route集合是有意义的。

这样做会简单得多,而且更清楚的是发生了什么。