2010-11-23 3 views
2

Я довольно новый с C# и .NET. Я пытаюсь смоделировать график с разнородными данными. Я имею в виду, я хотел бы быть в состоянии сделать что-то вроде этого:Пробуждение дженериков и графическое моделирование

// 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; 
    } 
} 

Строительство это так:

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)); 

Но, конечно, определение графика класс не позволит мне сделать это:

public class Graph<T> where T : CommonBaseClass 

Я также попытался определить базовый класс для человека и компьютера, но, конечно, он не работает. Любое предложение помощи/идеи? Мне нужны гетерогенные данные, потому что мне нужно объединить список разных узлов.

Спасибо за помощь!

+0

Пожалуйста, пост пример компиляции кода со всем необходимым кодом, особенно в том числе определение `Graph `, `` Person` и Computer`. – 2010-11-23 23:28:29

ответ

4

В подобных случаях может быть удобно, чтобы ваши родовые классы были получены из не-общих классов. Таким образом, вы можете обратиться ко всем типам узлов с помощью простого Node класса:

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; } 
    } 
} 

Если тип object слишком примитивно, вы можете использовать общие ограничения вместо:

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 
{ 
    // ... 
} 

Теперь ваш Graph класс может позволить любой тип Node и Edge:

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

+1, я использовал этот шаблон много раз раньше. Часто вы также можете использовать INode и IEdge вместо конкретной реализации. – cordialgerm 2010-11-24 01:15:48

2

Вы можете использовать интерфейс (скажем, IGraphItem) вместо общего базового класса и иметь как узлы, так и Edges реализующие IGraphItem.

Затем график может быть изменен на:

public class Graph<T> where T : IGraphItem 

Позвольте мне знать, если я неправильно понял вопрос, я не 100% уверен, что это то, что вы спрашивали о ...

+0

Я использовал что-то очень похожее на это, чтобы решить довольно похожую проблему. – 2010-11-23 23:30:45

1

Yoy может сделать это, 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; 
    } 
} 

И использование:

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

person.Nodes.Add(computer); 
computer.Nodes.Add(person); 
Смежные вопросы