2010-11-23 28 views
2

Je suis assez nouveau avec C# et .NET. J'essaie de modéliser un graphique avec des données hétérogènes. Je veux dire que je voudrais être en mesure de faire quelque chose comme ceci:Gâcher avec les génériques et la modélisation graphique

// Simple graph modeling using generics 
public class Node<T> 
{ 
    private T data; 
    public Node(T data) 
    { 
    this.data = data; 
    } 
} 

public class Edge<T, U> 
{ 
    private T source; 
    private U destination; 

    public Edge(T source, U destination) 
    { 
    this.source = source; 
    this.destination = destination; 
    } 
} 

il Construire cette façon:

Node<Person> p = new Node<Person>(new Person("Red John")); 
Node<Computer> c = new Node<Computer>(new Computer("MyComputer")); 
graph.AddNode(p); 
graph.AddNode(c); 
graph.AddEdge(new Edge<Person, Computer>(p, c)); 

Mais bien sûr, la définition de la classe graphique ne me laisse pas le faire:

public class Graph<T> where T : CommonBaseClass 

J'ai également essayé de définir une classe de base pour la personne et l'ordinateur, mais bien sûr, cela ne fonctionne pas. Toute suggestion d'aide/idée? J'ai besoin de données hétérogènes parce que je dois fusionner la liste des différents nœuds.

Merci de votre aide!

+0

S'il vous plaît poster un exemple de code de compilation avec tous les codes nécessaires, y compris en particulier la définition de '' Graphique , '' Person' et Computer'. –

Répondre

4

Dans de tels cas, il peut être pratique que vos classes génériques dérivent de classes non génériques. De cette façon, vous pouvez vous référer à tous les types de nœuds par un simple Node classe:

public class Node 
{ 
    public Node(object data) 
    { 
     this.Data = obj; 
    } 

    public object Data { get; protected set; } 
} 

public class Node<T> : Node 
{ 
    public Node(T data) : base(data) { } 

    new public T Data 
    { 
     get { return (T)base.Data; } 
    } 
} 

Si le type object est trop primitive, vous pouvez utiliser des contraintes génériques à la place:

public class Node 
{ 
    public Node(IGraphData data) 
    { 
     this.Data = obj; 
    } 

    public IGraphData Data { get; protected set; } 
} 

public class Node<T> : Node where T : IGraphData 
{ 
    public Node(T data) : base(data) { } 

    new public T Data 
    { 
     get { return (T)base.Data; } 
    } 
} 

public class Edge 
{ 
} 

public class Edge<T, U> : Edge 
    where T : Node where U : Node 
{ 
    // ... 
} 

Maintenant, votre Graph classe peut permettre à tout type de Node et Edge:

public class Graph 
{ 
    public void AddNode(Node node) { /* ... */ } 
    public void AddEdge(Edge edge) { /* ... */ } 
} 
+0

+1, j'ai utilisé ce modèle plusieurs fois auparavant. Souvent, vous pouvez également utiliser un INode et IEdge au lieu d'une implémentation concrète – cordialgerm

+0

Merci, J'aime cette solution, fonctionne comme le charme. – gremo

+0

IGraphData définition n'existe pas, je ne vois pas comment votre deuxième exemple compile. – Exegesis

2

Vous pouvez utiliser une interface (disons IGraphItem) au lieu d'une classe de base commune, et les nœuds et les édifices implémentent IGraphItem.

Puis graphique pourrait être changé pour:

public class Graph<T> where T : IGraphItem 

Laissez-moi savoir si je l'ai mal compris la question, je ne suis pas 100% sûr que ce soit ce que vous demandiez ...

+0

J'ai utilisé quelque chose de très similaire à cela pour résoudre un problème assez similaire. –

1

Yoy peut le faire par interface

public interface INode 
{ 
    List<INode> Nodes { get; set; } 
} 

public class Person : INode 
{ 
    public List<INode> Nodes { get; set; } 

    private string _name; 

    public Person(string name) 
    { 
     _name = name; 
    } 
} 

public class Computer : INode 
{ 
    public List<INode> Nodes { get; set; } 

    private int _number; 

    public Computer(int number) 
    { 
     _number = number; 
    } 
} 

Et:

var person = new Person("P1"); 
var computer = new Computer(1); 

person.Nodes.Add(computer); 
computer.Nodes.Add(person);