Messing up with generics and graph modelling
I'm pretty new with C# and .NET. I'm trying to model a graph with heterogeneous data. I mean i would like to be able to do something like this:
// 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;
}
}
Building it this way:
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));
But of course the graph class definition won't let me开发者_如何转开发 do this:
public class Graph<T> where T : CommonBaseClass
I've also tried defining a base class for both person and computer, but of course it's not working. Any help/idea suggestion? I need heterogeneous data because i have to merge list of different nodes.
Thanks for helping!
In cases like this, it can be convenient to have your generic classes derive from non-generic classes. That way, you can refer to all types of Nodes through a simple Node
class:
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; }
}
}
If type object
is too primitive, you can use generic constraints instead:
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
{
// ...
}
Now, your Graph
class can allow any type of Node
and Edge
:
public class Graph
{
public void AddNode(Node node) { /* ... */ }
public void AddEdge(Edge edge) { /* ... */ }
}
You could use an interface (say IGraphItem) instead of a common base class, and have both Nodes and Edges implement IGraphItem.
Then Graph could be changed to:
public class Graph<T> where T : IGraphItem
Let me know if I've misunderstood the question, I'm not 100% sure this is what you were asking about...
Yoy can do this by 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;
}
}
And use:
var person = new Person("P1");
var computer = new Computer(1);
person.Nodes.Add(computer);
computer.Nodes.Add(person);
精彩评论