图表遍历的C#和委托:如何改进代码的重用

时间:2012-11-12 13:05:49

标签: c# oop graph delegates

我正在进行图表实施。 My Graph类看起来像这样:

public class Graph<VERTEX_TYPE, EDGE_TYPE, IDENTIFIER_TYPE> 
    where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
    where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
    where IDENTIFIER_TYPE : IConvertible
{
...
}

(请不要关心已实施的界面,它们与问题无关)。

Vertex和Edge类都包含一些可以通过这种方式访问​​的通用数据:

public class Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE>  
    where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
    where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
{
    public VERTEX_TYPE Data{get;private set;}
    ....
}

public class Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> 
    where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
    where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
{

    public EDGE_TYPE Data{get;private set;}
    ....
}

现在我有一个实现一些算法的GraphVisitor类。遍历Graph时,我希望在算法遍历的两个边和顶点上调用一些委托。

我定义了两对委托,一对与必须在图元素上执行的操作相关,例如Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE>。 第二对代表与仅对数据持有的操作有关。

public class GraphVisitor<VERTEX_TYPE, EDGE_TYPE, IDENTIFIER_TYPE> 
    where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
    where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
    where IDENTIFIER_TYPE : IConvertible

{
    public delegate void VertexDataOperation(VERTEX_TYPE vertex);
    public delegate void EdgeDataOperation(EDGE_TYPE vertex);
    public delegate void VertexOperation(Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> vertex);
    public delegate void EdgeOperation(Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> vertex);
       .....
}

我已经实现了BFS算法(我避免发布整个实现),将两个委托作为参数:

public void BFS(VertexOperation op, EdgeOperation edgeOp)
{
...      
Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> currentVertex;
op(currentVertex);

foreach (Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> e in currentVertex.NeighBors())
{
    edgeOp(e);
    ...
}
... 

我正在尝试为VertexDataOperationEdgeDataOperation编写BFS版本,当我意识到我最终应该复制我的所有BFS代码以便使用2个不同的委托参数类型:

public void BFS(VertexDataOperation op, EdgeDataOperation edgeOp)
...
Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> currentVertex;
op(currentVertex.Data); //method differs only here

foreach (Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> e in currentVertex.NeighBors())
{
    edgeOp(e.Data);//method differs only here
    ...
}

我想避免使用相同方法的相同实现。唯一改变的是方法签名和调用方法的对象。

有没有人有任何想法来改进此代码的设计?

编辑:

我可以将所有4个代表传递给一个函数,但是我在每次遍历时只使用它们中的一对,所以它看起来不太干净。

1 个答案:

答案 0 :(得分:1)

首先,我强烈建议您更改类型参数的命名。惯例是使用T前缀,然后使用PascalCased名称,例如TVertexTEdge

接下来,如果您发现自己想要几个相关的委托,那听起来您真的想要一个具有多种方法的界面。您始终可以创建接口的无操作实现,以允许仅覆盖一个方法 - 或者甚至提供静态方法,如果要使用lambda表达式来表达操作,则可以从委托创建具体实现的实例。 / p>

这基本上是Reactive Extensions对IObserver<T>界面的作用,而且效果非常好。