2017-05-27 2 views
0

Ich habe zwei Arten von Knoten, eine ist MyLinkNode, die als Basis verwendet wird, eine andere ist GraphNode, die Vererbung MyLinkNode.C# generisch, wo T-Klasse: (Vererbungsklasse)

Ich versuche, MyQueue mit MyLinkNode zu erstellen. Alles ist in Ordnung, bis ich versuche, GraphNode zu MyQueue hinzuzufügen. Ich kann MyQueue nicht mit GraphNode verwenden, da es größer ist.

Eine andere Möglichkeit ist das Erstellen einer anderen Warteschlange für GraphNode, aber das bedeutet, dass ich viele Klassen erstellen müsste, wenn ich mehr Knoten habe. Gibt es einen Vorschlag?

public class MyQueue<T> where T : MyLinkNode<T> 
{ 
    private T Head; 
    private T Last; 
    public MyQueue(){ ... } 
    public void Enqueue(T item) 
    { 
     item.Prev = Last; 
     Last.Next = item; 
     Last = item; 
    } 
} 
public class MyGraphQueue 
{ 
    //everything is the same with MyQueue besides the Node Type 
    //I don't want to create like this. 
    private GraphNode Head; 
    private GraphNode Last; 
    public MyGraphQueue(){ ... } 
    public void Enqueue(GraphNode item) 
    { 
     item.Prev = Last; 
     Last.Next = item; 
     Last = item; 
    } 
} 
public class MyLinkNode<T> 
{ 
    public T data { get; set; } 
    public MyLinkNode<T> Next { get; set; } 
    public MyLinkNode<T> Prev { get; set; } 
} 
public class GraphNode<T> : MyLinkNode<T> 
{ 
    public GraphNode() 
    { 
     this.adjacencyNodes = new List<GraphNode<T>>(); 
     this.isVisited = false; 
    } 

    public List<GraphNode<T>> adjacencyNodes; 
    public bool isVisited { get; set; } 
} 
public void BFS<T>(GraphNode<T> v) 
{ 
    MyQueue<GraphNode<T>> queue = new MyQueue<GraphNode<T>>(); // error, can't implicit convert GraphNode to MyLinkNode<T> 
    MyGraphQueue queue = new MyGraphQueue(); //It's how I do now. 

} 
+0

Ich verstehe nicht, was du meinst mit "kann MyQueue nicht mit GraphNode verwenden, da es größer ist." –

+0

Entschuldigung für meine schlechte Erklärung. Wenn ich MyQueue mit GraphNode verwende, würde der Compiler sagen, dass es illegal ist, da GraphNode nicht implizit in MyLinkNode konvertiert werden kann. –

Antwort

0

Dies ist ein standardmäßiges Generics-Vererbungsproblem. Sie müssen das, was die Warteschlange benötigt, vom generischen Typ trennen. Fügen Sie einfach eine weitere Basisklasse für die Warteschlangeneinschränkung hinzu.

Dadurch behält die Warteschlange die Garantie für alle Elemente vom Typ T und erfordert keine zusätzlichen Typen oder mehrere Klassendefinitionen für alle konkreten Typen. Eric Libert hat einen guten Artikel here darüber, warum diese Beschränkung in dem Generikasystem erforderlich war.

public class CallingClass 
{ 
    public void BFS(GraphNode v) 
    { 
     MyQueue<GraphNode> queue = new MyQueue<GraphNode>(); // error, can't implicit convert GraphNode to MyLinkNode<T> 
     // MyGraphQueue queue = new MyGraphQueue(); //It's how I do now. 

    } 
} 
public class QueueItem 
{ 
    public QueueItem Next { get; set; } 
    public QueueItem Prev { get; set; } 
} 

public class MyQueue<T> where T : QueueItem 
{ 
    private T Head; 
    private T Last; 
    public MyQueue() { } 
    public void Enqueue(T item) 
    { 
     item.Prev = Last; 
     Last.Next = item; 
     Last = item; 
    } 
} 

public class MyLinkNode<T>: QueueItem 
{ 
    public T data { get; set; } 

} 
public class GraphNode : MyLinkNode<string> 
{ 
    public GraphNode() 
    { 
     this.adjacencyNodes = new List<GraphNode>(); 
     this.isVisited = false; 
    } 

    public List<GraphNode> adjacencyNodes; 
    public bool isVisited { get; set; } 
} 
+1

Danke, du hast meinen Standpunkt, eine elegante Verwendung. Danke noch einmal. –

0

Das ist nicht überraschend. Sie müssen

public class MyQueue<T, S> where T : MyLinkNode<S> 
{ 
    private T Head; 
    private T Last; 
    public MyQueue() { } 
    public void Enqueue(T item) 
    { 
     item.Prev = Last; 
     Last.Next = item; 
     Last = item; 
    } 
} 

public void BFS(GraphNode v) 
{ 
    MyQueue<GraphNode, string> queue = new MyQueue<GraphNode, string>(); 
} 
1

MyQueue<T> where T : MyLinkNode<T> können hier MyLinkNode<string>

Beacuse nicht akzeptieren T Zeichenfolge ist. aber offensichtlich string erbt nicht von MyLinkNode

Ich denke, die Lösung ist einfacher als Sie sich vorstellen.

gesetzt einfach die Art (T) des Wertes in der Warteschlange und den Innenbereich MyLinkNode<T>:

public class MyQueue<T> 
{ 
    private MyLinkNode<T> Head; 
    private MyLinkNode<T> Last; 

    public void Enqueue(MyLinkNode<T> item) 
    { 
     item.Prev = Last; 
     Last.Next = item; 
     Last = item; 
    } 
} 

public void BFS(GraphNode v) 
{ 
    MyQueue<string> queue = new MyQueue<string>(); // no error anymore 
    queue.Enqueue(v); 
} 
-1

Das Problem, aus dem ersten Zeile kommt.

Verwendung:

public class MyQueue<T> where T : MyLinkNode<string> { } 

Statt:

public class MyQueue<T> where T : MyLinkNode<T> { } 

und es wird gut funktionieren.