在模板树上搜索
所以我有 2 个接口:
一个可以有子节点的节点
public interface INode
{
IEnumeration<INode> Children { get; }
void AddChild(INode node);
}
和一个可以有与之关联的数据的派生“数据节点” 请
public interface IDataNode<DataType> : INode
{
DataType Data;
IDataNode<DataType> FindNode(DataType dt);
}
记住,树中的每个节点都可以有一个不同的数据类型与其关联作为其数据(因为INode.AddChild 函数仅采用基本 INode)
以下是 IDataNode 接口的实现:
internal class DataNode<DataType> : IDataNode<DataType>
{
List<INode> m_Children;
DataNode(DataType dt)
{
Data = dt;
}
public IEnumerable<INode> Children
{
get { return m_Children; }
}
public void AddChild(INode node)
{
if (null == m_Children)
m_Children = new List<INode>();
m_Children.Add(node);
}
public DataType Data { get; private set; }
问题是,在不知道在树中会遇到哪种 DataType 的情况下,如何实现 FindNode 函数?
public IDataNode<DataType> FindNode(DataType dt)
{
throw new NotImplementedException();
}
}
正如您可以想象的那样,
public IDataNode<DataType> FindNode(DataType dt)
{
IDataNode<DataType> result = null;
foreach (var child in Children)
{
if (child is IDataNode<DataType>)
{
var datachild = child as IDataNode<DataType>;
if (datachild.Data.Equals(dt))
{
result = child as IDataNode<DataType>;
break;
}
}
else
{
// What??
}
// Need to recursively call FindNode on the child
// but can't because it could have a different
// DataType associated with it. Can't call FindNode
// on child because it is of type INode and not IDataNode
result = child.FindNode(dt); // can't do this!
if (null != result)
break;
}
return result;
}
当我知道我使用的特定树将具有什么类型的数据类型时,我唯一的选择是这样做吗?也许我以错误的方式处理这个问题,所以任何提示都会受到赞赏。谢谢!
So I have 2 interfaces:
A node that can have children
public interface INode
{
IEnumeration<INode> Children { get; }
void AddChild(INode node);
}
And a derived "Data Node" that can have data associated with it
public interface IDataNode<DataType> : INode
{
DataType Data;
IDataNode<DataType> FindNode(DataType dt);
}
Keep in mind that each node in the tree could have a different data type associated with it as its Data (because the INode.AddChild function just takes the base INode)
Here is the implementation of the IDataNode interface:
internal class DataNode<DataType> : IDataNode<DataType>
{
List<INode> m_Children;
DataNode(DataType dt)
{
Data = dt;
}
public IEnumerable<INode> Children
{
get { return m_Children; }
}
public void AddChild(INode node)
{
if (null == m_Children)
m_Children = new List<INode>();
m_Children.Add(node);
}
public DataType Data { get; private set; }
Question is how do I implement the FindNode function without knowing what kinds of DataType I will encounter in the tree?
public IDataNode<DataType> FindNode(DataType dt)
{
throw new NotImplementedException();
}
}
As you can imagine something like this will not work out
public IDataNode<DataType> FindNode(DataType dt)
{
IDataNode<DataType> result = null;
foreach (var child in Children)
{
if (child is IDataNode<DataType>)
{
var datachild = child as IDataNode<DataType>;
if (datachild.Data.Equals(dt))
{
result = child as IDataNode<DataType>;
break;
}
}
else
{
// What??
}
// Need to recursively call FindNode on the child
// but can't because it could have a different
// DataType associated with it. Can't call FindNode
// on child because it is of type INode and not IDataNode
result = child.FindNode(dt); // can't do this!
if (null != result)
break;
}
return result;
}
Is my only option to do this when I know what kinds of DataType a particular tree I use will have? Maybe I am going about this in the wrong way, so any tips are appreciated. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您需要将
FindNode
方法放入INode
中。否则,在找到DataType
类型的节点之前,您无法找到某种类型DataType
的节点。即使您知道的对象是DataNode
的引用,如果有人告诉您查找DataNode
DataNode
,这对您也无济于事;Y>
。现在您可以采取两条路:如果您希望将
DataNode
模板化,那么您需要在编译时了解树中所有可能的数据类型。如果您知道这一点,则可以使用通用的 DataNode。如果您有可能想要找到一个节点,该节点包含某种类型的数据,而这些数据只能在运行时为您所知(例如,从您无法控制的某些方法的返回值),那么您不能使用泛型。我将在下面说明通用解决方案。
INode.FindNode
可以这样实现:我不得不说,上面使用 LINQ 的递归实现可能过于聪明,并且可能不太容易理解。它总是可以用
foreach
编写,以使其更清晰。First of all, you need to put the
FindNode
method inINode
. Otherwise, you cannot find a node of some typeDataType
... before having found a node of typeDataType
. Even if you have a reference to an object that you know is aDataNode<X>
, this won't help you if someone tells you to find aDataNode<Y>
.There are now two roads you may take: if you want
DataNode
to be templated, then you need to know all possible types of data in the tree at compile time. If you know that, you can use a genericDataNode
. If there's a chance that you may want to find a node with data of some type that will only become known to you at runtime (e.g. from the return value of some method that you do not control) then you cannot use generics.I will illustrate the generic solution below.
INode.FindNode
could be implemented like this:I have to say that the above recursive implementation with LINQ tries perhaps to be too clever and is maybe not very easy to understand. It could always be written with
foreach
, to make it more clear.使用通用函数:
然后像这样调用它:
Use a Generic Function:
Then you call it like this: