在类声明中参数化通用接口

时间:2015-08-03 21:16:30

标签: c# generics

所以我需要使用已经在代码的另一部分中计算的顶点和边来实现搜索(我将该部分视为黑盒子)。

所以我有我的图表,有一个顶点和边的列表:

class Graph {
    List<Vertex> vertices;
    List<Edge> edges;
}

我决定为搜索创建一个通用实现,并为顶点创建一个包装器:

class Node<T> {...}

并为边创建了一个接口,以便我可以在搜索中使用它们:

interface ISearchLink<T> {...}

因此,搜索方法标题如下所示:

public static List<Node<T>> Search(List<Node<T>> nodes, List<ISearchLink<T>> links);

现在,因为边缘已经使用了我想要的类型,并且为了使它与其他部分保持一致,我将Edge类声明更改为这样(并实现了接口方法):

class Edge : ISearchLink<Vertex> {...}

所以现在当我调用搜索时,它说我的参数无效

List<Node<T>> table = search(vertices, edges);

这似乎表明边缘声明无效(即使我没有得到VS的投诉)。 此声明是否无效,如果是,为什么没有错误? 如果它不是无效的,那么问题似乎是什么? (似乎VS无法将List«Edge»转换为List«ISearchLink«Vertex»»)

编辑: 具体的错误是:

The best overloaded method match for Node<Vertex>.search(System.Collections.Generic.List<Vertex>, System.Collections.Generic.List<ISearchLink<Vertex>>)' has some invalid arguments

cannot convert from 'System.Collections.Generic.List<Edge>' to 'System.Collections.Generic.List<ISearchLink<Vertex>>'

2 个答案:

答案 0 :(得分:1)

问题是您的搜索方法正在列入列表:

public static List<Node<T>> Search<T>(List<Node<T>> nodes, List<ISearchLink<T>> links)

当你说“似乎VS无法将List<Edge>转换为List<ISearchLink<Vertex>>”时,那是因为List<Edge> 确实不是 a {{1 }}。 VS 不应为您进行转换,因为List<ISearchLink<Vertex>> List<T>位于T

通过说你的方法应该接受List,你告诉调用者你可以访问和使用该集合中的项目(这意味着你期望作为参数的类型必须可以从键入调用者提供的),但您也可以在该集合中插入一些内容(这意味着调用者提供的类型必须可以从您期望的类型中分配)!这会将调用者锁定为提供完全预期的类型。

另一方面,

IEnumerable<T>T中是协变的。您无法将新项目插入IEnumerable<T>;你只能拿出东西。这意味着您期望作为参数的类型必须可以从调用者提供的类型中分配 - 这与您期望ISearchLink<T>的情况相对应,可以从Edge分配。但是如果调用者提供的类型不能从期望的类型作为参数分配,那就没问题,因为在那个方向上不会有任何分配。

因此将功能更改为具有签名

public static List<Node<T>> Search<T>(List<Node<T>> nodes, IEnumerable<ISearchLink<T>> links)

现在VS会很高兴地将List<Edge>转换为IEnumerable<ISearchLink<Vertex>>,因为它知道你只会从列表中删除内容而不会将MyEvilSearchLink<Vertex>>插入到{实际上是List<Edge>

答案 1 :(得分:0)

正确的函数头

public static List<Node<T>> Search<T>(List<Node<T>> nodes, List<ISearchLink<T>> links)
{

}

请勿忘记<T>

之后的Search