Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c中自定义委托的示例用法_C#_Delegates_Tree_Parent Child - Fatal编程技术网

C# c中自定义委托的示例用法

C# c中自定义委托的示例用法,c#,delegates,tree,parent-child,C#,Delegates,Tree,Parent Child,我发现了关于C中树实现的问题。我不知道委托,我想知道下面的代码如何用于实现树。另外,跟踪父节点最有效的方法是什么 delegate void TreeVisitor<T>(T nodeData); class NTree<T> { T data; LinkedList<NTree<T>> children; public NTree(T data) { this.data = data;

我发现了关于C中树实现的问题。我不知道委托,我想知道下面的代码如何用于实现树。另外,跟踪父节点最有效的方法是什么

delegate void TreeVisitor<T>(T nodeData);

class NTree<T>
{
    T data;
    LinkedList<NTree<T>> children;

    public NTree(T data)
    {
        this.data = data;
        children = new LinkedList<NTree<T>>();
    }

    public void addChild(T data)
    {
        children.AddFirst(new NTree<T>(data));
    }

    public NTree<T> getChild(int i)
    {
        foreach (NTree<T> n in children)
            if (--i == 0) return n;
        return null;
    }

    public void traverse(NTree<T> node, TreeVisitor<T> visitor)
    {
        visitor(node.data);
        foreach (NTree<T> kid in node.children)
            traverse(kid, visitor);
    }        
}
委托基本上允许您谈论满足某些条件的任意函数,而不必确切地知道您所谈论的函数

考虑以下用于遍历树并对每个元素执行操作的代码:

void DoSomethingToAllNodes(NTree<T> node)
{
    DoSomething(node);
    foreach (var child in node.Children)
        DoSomethingToAllNodes(child);
}
它是有效的,但它相当不灵活。我们必须为要在节点上执行的每个不同操作重新实现该方法:

void DoSomethingElseToAllNodes(NTree<T> node)
{
    DoSomethingElse(node);
    foreach (var child in node.Children)
        DoSomethingElseToAllNodes(child);
}
相反,我们可以声明一个委托来表示以一个NTree作为参数的任何方法,但不返回任何内容,然后我们可以接受满足该条件的方法作为参数。然后,我们可以实现一个遍历方法来处理每一种可能性,而不必为每一个不同的操作重新实现它。

委托基本上允许您谈论满足某些条件的任意函数,而不必确切地知道您在谈论什么函数

考虑以下用于遍历树并对每个元素执行操作的代码:

void DoSomethingToAllNodes(NTree<T> node)
{
    DoSomething(node);
    foreach (var child in node.Children)
        DoSomethingToAllNodes(child);
}
它是有效的,但它相当不灵活。我们必须为要在节点上执行的每个不同操作重新实现该方法:

void DoSomethingElseToAllNodes(NTree<T> node)
{
    DoSomethingElse(node);
    foreach (var child in node.Children)
        DoSomethingElseToAllNodes(child);
}

相反,我们可以声明一个委托来表示以一个NTree作为参数的任何方法,但不返回任何内容,然后我们可以接受满足该条件的方法作为参数。然后我们可以实现一种遍历所有可能的遍历方法,而不是必须为每个不同的操作重新实现它。

如果您完全熟悉C或C++,则可以将委托看作是类型安全的函数指针。这就是我如何设法让一个委托人对我与之交谈过的大多数人的看法。

< P>如果你完全熟悉C或C++,那么委托可以被认为是一种类型安全的函数指针。这就是我如何设法了解委托对我与之交谈过的大多数人的影响。

您的代码所做的是声明一个委托,它基本上是一个方法的签名。traverse方法接受签名与您声明为参数的委托匹配的任何函数并调用它。为了好玩,一切都是通用的

delegate void TreeVisitor<T>(T nodeData);

//  This function takes a handle to a method as a parameter,
//  and invokes that method for each node
public void traverse(NTree<T> node, TreeVisitor<T> visitor) {
    visitor(node.data);
    ...
}
可以称之为:

public class MyEvilPlans {

    public void WreakHavoc<int>(int nodeData) {
        Console.WriteLine("The secret to life is:  {0}", nodeData.ToString());
    }

    public void PlayWithTree() {
        NTree<int> tree = new NTree<int>();

        //  Initialize tree

        //  If the tree has 47 nodes, WreakHavoc will be called 47 times,
        //  once for each node in the tree.
        tree.traverse(WreakHavoc);
    }

}
访问者模式允许您决定为树的每个节点执行什么代码。。。其他人控制树的实现,但您通过预定义的委托契约控制对树行为的响应。在某种程度上,它破坏了封装,因为您知道所调用方法的内部细节:它将为每个节点回调您。但这就是访问者模式的全部内容:

要回答问题的第二部分,如何跟踪父节点。。。你拥有的是非二叉树。为了能够从任何节点遍历备份树,您必须为每个NTree指定一个名为“parent”的NTree类型的成员。这应该由NTree的构造函数设置,以便:

//  Added the handle to 'this'
children.AddFirst(new NTree<T>(data, this));

您可以找到关于非二叉树的精彩讨论。

您的代码所做的是声明一个委托,它基本上是一个方法的签名。traverse方法接受签名与您声明为参数的委托匹配的任何函数并调用它。为了好玩,一切都是通用的

delegate void TreeVisitor<T>(T nodeData);

//  This function takes a handle to a method as a parameter,
//  and invokes that method for each node
public void traverse(NTree<T> node, TreeVisitor<T> visitor) {
    visitor(node.data);
    ...
}
可以称之为:

public class MyEvilPlans {

    public void WreakHavoc<int>(int nodeData) {
        Console.WriteLine("The secret to life is:  {0}", nodeData.ToString());
    }

    public void PlayWithTree() {
        NTree<int> tree = new NTree<int>();

        //  Initialize tree

        //  If the tree has 47 nodes, WreakHavoc will be called 47 times,
        //  once for each node in the tree.
        tree.traverse(WreakHavoc);
    }

}
访问者模式允许您决定为树的每个节点执行什么代码。。。其他人控制树的实现,但您通过预定义的委托契约控制对树行为的响应。在某种程度上,它破坏了封装,因为您知道所调用方法的内部细节:它将为每个节点回调您。但这就是访问者模式的全部内容:

要回答问题的第二部分,如何跟踪父节点。。。你拥有的是非二叉树。为了能够从任何节点遍历备份树,您必须为每个NTree指定一个名为“parent”的NTree类型的成员。这应该由NTree的构造函数设置,以便:

//  Added the handle to 'this'
children.AddFirst(new NTree<T>(data, this));

您可以找到关于非二叉树的精彩讨论。

顺便说一句,对于返回void的委托,预定义的泛型操作委托已经足够好了,无需声明自己的操作。我听说过操作,但由于我对委托一无所知,所以我想从这里开始。顺便说一句,对于返回void的委托,预定义的通用操作委托已经足够好了,无需声明自己的操作。我听说过操作,但由于我对委托一无所知,所以我想我应该从这里开始。谢谢,这很好
这很有道理。谢谢你付出了额外的努力,把所有的代码都打出来。谢谢,这很有意义。谢谢你多做了一点,把所有的代码都打出来了