简体   繁体   English

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

[英]Parameterizing a generic interface in class declaration

So I needed to implement a search using vertices and edges that are already being computed in another part of the code (I'm treating that part like a black box). 所以我需要使用已经在代码的另一部分中计算的顶点和边来实现搜索(我将该部分视为黑盒)。

So I have my graph, with a list of vertices and edges: 所以我有我的图表,有一个顶点和边的列表:

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

I decided to make a generic implementation for the search, and created a wrapper for the vertices: 我决定为搜索创建一个通用实现,并为顶点创建一个包装器:

class Node<T> {...}

and created an interface for the edges so that I can use them in the search: 并为边创建了一个接口,以便我可以在搜索中使用它们:

interface ISearchLink<T> {...}

as a result, the search method header looks like this: 因此,搜索方法标题如下所示:

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

now, because the edges are already using the type I wanted them to, and to keep it consitent with the other part, I changed the Edge class declaration to look like this (and implemented the interface methods): 现在,因为边缘已经使用了我想要的类型,并且为了使它与其他部分保持一致,我将Edge类声明更改为这样(并实现了接口方法):

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

so now when I call the search, it says I have invalid arguments 所以现在当我打电话给搜索时,它说我的论点无效

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

which seems to indicate that the Edge declaration is invalid (even though I got no complaints from VS). 这似乎表明边缘声明无效(即使我没有得到VS的投诉)。 Is this declaration invalid and if so, why is there no error? 此声明是否无效,如果是,为什么没有错误? And if it isn't invalid, what seems to be the problem? 如果它不是无效的,那么问题似乎是什么? (it seems VS can't convert List«Edge» to List«ISearchLink«Vertex»») (似乎VS无法将List«Edge»转换为List«ISearchLink«Vertex»»)

edit: the errors in specific are: 编辑:具体的错误是:

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

and

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

The problem is that your Search method is taking in Lists: 问题是您的搜索方法正在列入列表:

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

When you say "it seems VS can't convert List<Edge> to List<ISearchLink<Vertex>> ", that's because a List<Edge> really isn't a List<ISearchLink<Vertex>> . 当你说“似乎VS无法将List<Edge>转换为List<ISearchLink<Vertex>> ”时,那是因为List<Edge> 确实不是 List<ISearchLink<Vertex>> VS shouldn't convert like this for you, because List<T> is invariant in T . VS 不应该为你转换,因为List<T>T不变的。

By saying that your method should take in List s, you are telling the caller that you could access and use items in that collection (which means that the type you are expecting as a parameter must be assignable from the type the caller provides), but you also might insert something into that collection (which means the type the caller provides must be assignable from the type you are expecting)! 通过说你的方法应该接受List ,你告诉调用者你可以访问和使用该集合中的项目(这意味着你期望作为参数的类型必须可以从调用者提供的类型中分配),但是你也可以在该集合中插入一些东西(这意味着调用者提供的类型必须可以从你期望的类型中分配)! This locks the caller in to providing exactly the expected type. 这将锁定调用者以提供完全预期的类型。

IEnumerable<T> , on the other hand, is covariant in T . 另一方面, IEnumerable<T>T是协变的。 You can't insert new items into an IEnumerable<T> ; 您不能将新项插入IEnumerable<T> ; you can only get stuff out. 你只能拿出东西。 That means that the type you are expecting as a parameter must be assignable from the type the caller provides- which corresponds to the situation where you are expecting ISearchLink<T> , which is assignable from Edge. 这意味着您期望作为参数的类型必须可以从调用者提供的类型中分配 - 这与您期望ISearchLink<T>的情况相对应,可以从Edge分配。 But it's fine if the type provided by the caller is not assignable from the type expected as a parameter, because there won't be any assignments flowing in that direction. 但是如果调用者提供的类型不能从预期作为参数的类型中分配,那就没问题,因为在该方向上不会有任何分配。

So change the function to have the signature 所以改变功能有签名

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

Now VS will happily convert the List<Edge> to IEnumerable<ISearchLink<Vertex>> , because it knows you're only going to be pulling stuff out of the list and not doing things like inserting MyEvilSearchLink<Vertex>> into what is actually a List<Edge> . 现在VS很乐意将List<Edge>转换为IEnumerable<ISearchLink<Vertex>> ,因为它知道你只会把东西从列表中拉出来并且不会像将MyEvilSearchLink<Vertex>>插入实际内容那样List<Edge>

The correct function header would 正确的函数头会

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

}

Don't forget the <T> after Search 不要忘记Search后的<T>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM