المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : Generics and type constraints



C# Programming
07-16-2009, 07:20 PM
Hi,

I'm toying around with generics and have run into a little problem. My class is a tree, but this is not about whether or not one should make a tree this way - what I'm trying to do adds complexity for just a little lazy-coding benefit, so please ignore the particular example - I just want to understand if what I wanted to do can be done with generics.

Here's the TreeNode class:


abstract public class TreeNode
{
TreeNode parent;
List children = new List();
T data;


public TreeNode() { }


public T Data
{
get { return data; }
set { data = value; }
}


public TreeNode Parent
{
get { return parent; }
set { parent = value; }
}


public List Children
{
get { return children; }
set { children = value; }
}
}


Now, let's say we want to derive a class for organizing tags into trees. The data is just a string, and for convenience we may want a constructor that sets the text of the node. I'm trying to see if there is a way to write a utility method that would take any treenode (necessarily derived since the base class is abstract) and a collection of node *data* objects and create child nodes with the data and parent set. The following snippet illustrates the Tag and how code might use the utility method to create a hard-coded hierarchy of tags:


public class Tag : TreeNode
{
public Tag() {}
public Tag(string text) { Data = text; }
}

class usingTags
{
Tag getBuiltIn()
{
Tag root = new Tag("Built-in");
Tag[] top = TreeUtil.Add(root, "License", "Product");
TreeUtil.Add(top[0], "CPOL", "MIT", "Proprietary");
TreeUtil.Add(top[1], "Banco", "Acco", "Piccolo");
return root;
}
}


Based on this, the utility method should be something like this:

static public TNode[] Add(TNode parent, params T[] data) where TNode : TreeNode, new()
{
List list;

if (parent == null)
list = parent.Children;
else
list = new List();

int startIndex = list.Count;

foreach (T item in data) list.Add(new TNode() { Data = item });
return list.GetRange(startIndex, list.Count - startIndex).ToArray();
}


Two problems present themselves:

1) The first assignment to "list" does not build, the compiler complaining it cannot convert List to List, which I think is odd since I have defined a type constraint which guarantees that TNode either is or is derived from TreeNode.

2) If I change that assignment so it assigns null instead, just to be able to build, the code *using* it does not compile. I thought the type of T could be inferred, since TNode is TreeNode and the params T[] parameter is an array of strings. But the compiler just says the method requries two type parameters.

Is there a way to solve these problems so the user of the utility method need only supply the node type to create and the actual values for node data?