【发布时间】:2011-01-31 20:27:05
【问题描述】:
我正在尝试找出是否有更好的方法来构建一些代码。尽管它目前有效,但由于泛型约束的复杂性和疯狂的性质,它总是让我感到困惑。我很想知道是否有人对更简洁的解决方案有想法。
我已经包含了一个类图,以使事情变得更容易一些。
这一切都在一个库中进行,我想尽量保持我所有的类型安全。该库有 3 层,其复杂性不断增加。我稍后会解释。
我正在使用泛型来使所有类型都工作。例如,Route 实际上是 List<T>,其中 T 是访问。现在因为我有 3 层,我希望能够从 Route 本身访问这些访问(以及它们对应的节点)的属性(并使其更易于使用)。所以这实际上是一个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 方差和泛型)。
总而言之,它有效,但至少可以说有点令人生畏。任何人都知道如何很好地重新工作?
【问题讨论】:
-
那个类图是用什么做的!?抱歉没有用的评论:我不得不问,它看起来很棒;)我发誓我看到了渐变等。如果是手工的话,我会整天捂脸。
-
你真的需要泛型吗?例如,为什么在 Visit 中有 Visit
而不是硬编码类型节点属性? -
@Steve:如果我没有泛型,那么当我不得不引入大量演员表时。例如,将 Level2.Visit 和 Level1.Visit 添加到 Route 之间没有区别。而我需要确保它们都是相同的类型,并且我可以访问它们的属性。如果不使用泛型,我将不得不一直在投射。
-
@Ian,我不确定是否理解。您已经定义了 Visit
,例如可以是 Visit 。你还有其他适合这个课程的课程吗? -
不是一个真正的答案,但我得出的结论是,一旦仿制药开始反击,就没有任何帮助。将它们降低到您严格需要的最低限度。那甚至可能根本没有。当然,集合应该是通用的——但我很想将这部分归为少数非通用接口。
标签: c# generics refactoring