所以我需要使用已经在代码的另一部分计算的顶点和边来实现搜索(我将那部分视为黑盒)。
所以我有我的图表,其中包含顶点和边的列表:
class Graph {
List<Vertex> vertices;
List<Edge> edges;
}
我决定为搜索做一个通用的实现,并为顶点创建一个包装器:
class Node<T> {...}
并为边缘创建了一个接口(interface),以便我可以在搜索中使用它们:
interface ISearchLink<T> {...}
因此,搜索方法标题如下所示:
public static List<Node<T>> Search(List<Node<T>> nodes, List<ISearchLink<T>> links);
现在,因为边缘已经在使用我希望它们使用的类型,并且为了使其与其他部分保持一致,我将 Edge 类声明更改为如下所示(并实现了接口(interface)方法):
class Edge : ISearchLink<Vertex> {...}
所以现在当我调用搜索时,它说我有无效的参数
List<Node<T>> table = search(vertices, edges);
这似乎表明 Edge 声明无效(即使我没有收到 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>>'
最佳答案
问题是您的搜索方法正在接受列表:
public static List<Node<T>> Search<T>(List<Node<T>> nodes, List<ISearchLink<T>> links)
当您说“似乎 VS 无法将 List<Edge>
转换为 List<ISearchLink<Vertex>>
”时,那是因为 List<Edge>
真的不是 List<ISearchLink<Vertex>>
. VS 不应该为你这样转换,因为List<T>
是invariant在 T
.
说你的方法应该接受 List
s,你告诉调用者你可以访问和使用该集合中的项目(这意味着你期望作为参数的类型必须可以从调用者提供的类型中分配),但你也可以向该集合中插入一些东西(这意味着调用者提供的类型必须可以从您期望的类型中分配)!这会将调用者锁定为提供准确的预期类型。
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>
.
关于c# - 在类声明中参数化通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31796900/