【问题标题】:What is the correct way to call an extension method (TreeNodeCollection Add method)?调用扩展方法(TreeNodeCollection Add 方法)的正确方法是什么?
【发布时间】:2018-06-30 18:31:08
【问题描述】:

我的代码的相关部分如下。在MyTreeView 类中(下面的最后一段代码),代码行TncExtensions.TncNodeAdd(this, myTreeViewNode); 生成错误CS7036 There is no argument given that corresponds to the required formal parameter 'myTreeViewNode' of 'TncExtensions.TncNodeAdd(TreeNodeCollection, MyTreeView_Abstract, MyTreeViewNode_Abstract)'

为什么编译器无法确定我的 TreeNodeCollection 扩展方法的第二个形参是什么?

public static class TncExtensions
{
    public static int TncNodeAdd(this TreeNodeCollection nodes, MyTreeView_Abstract myTreeView, MyTreeViewNode_Abstract myTreeViewNode)
    {
        return myTreeView.Nodes.Add(myTreeViewNode);
    }
}

public abstract class MyTreeViewNode_Abstract : TreeNode
{
    public MyTreeViewNode_Abstract(string text) : base(text)
    {
    }
}

public class MyTreeViewNode : MyTreeViewNode_Abstract
{
    public MyTreeViewNode(string text) : base(text)
    {
    }
}

public abstract class MyTreeView_Abstract : TreeView
{
}

public class MyTreeView : MyTreeView_Abstract
{
    public void CreateTree()
    {
        MyTreeViewNode myTreeViewNode = new MyTreeViewNode("node text");
        TncExtensions.TncNodeAdd(this, myTreeViewNode);
    }
}

【问题讨论】:

  • 您声明了一个扩展方法,但您像使用普通静态方法一样使用它。如果您像普通静态方法一样调用它,则需要提供 all 参数(在您的情况下是 3,而不仅仅是 2)。也就是说,尝试像普通静态方法一样调用扩展方法看起来有点不对劲。也许可以查看有关扩展方法的教程,以阐明它们通常是如何使用/调用的。
  • 你使用的扩展方法不对。
  • 另外,你的扩展方法中 nodes 参数的具体目的是什么?你的扩展方法没有使用nodes,那么它有什么意义呢?
  • @HansPassant:我不同意。最初,我使用基本TreeNodeCollection Add 方法将自定义TreeView 节点添加到自定义TreeView。在我的自定义TreeView 中,我有一些自定义属性来跟踪我的自定义TreeView 的状态。在没有钩子到Add 方法的情况下,我必须在each 调用基本Add 方法之后立即使用内联代码更新自定义属性。通过使用Add 扩展方法和将自定义节点绑定到自定义TreeView 的自定义属性,我可以在一个中心位置更新自定义TreeView 属性。

标签: c# winforms extension-methods treenodecollection


【解决方案1】:

我相信您创建的扩展方法没有多大用处,但如果您想知道问题所在,那么您使用的扩展方法是错误的。您像静态方法一样访问它,在这种风格中,您需要根据方法的签名传递 3 个参数:

TncExtensions.TncNodeAdd(Nodes, this, myTreeViewNode);

或者像扩展方法一样使用它:

this.Nodes.TncNodeAdd(this, myTreeViewNode);

我建议你把扩展方法改成:

public static int TncNodeAdd(this TreeNodeCollection nodes, MyTreeViewNode_Abstract myTreeViewNode)
{
    return nodes.Add(myTreeViewNode);
}

要了解更多信息,请查看Extension Methods

【讨论】:

  • 感谢您正确使用扩展方法的指导。我没有得到它(显然)。扩展方法看起来并不多,因为我只提供了提出问题所需的最少代码。既然你已经教会了我如何正确调用扩展方法,我就可以达到original override question中所说的目标:increment/decrement custom integer properties that are part of my MyTreeView class at the same time I Add a MyTreeViewNode to my MyTreeView
  • p.s.:在我用你的回答修改我的调用代码为 IAW 后,我能够将扩展方法重命名为简单的 Add
  • 可以,没有命名冲突。
  • 再更新一次(你的答案仍然是公认的答案)
【解决方案2】:

Reza'a answer 仍然是答案,但为了使我的 treenode Add 扩展方法有用,我不得不修改对它的调用。我忘记了,作为添加树节点的一部分,您需要指定要将新节点附加到哪个节点集合。

注意:有关所涉及的基本类,请参见原始问题中的代码

修改了 Reza 建议的添加扩展方法

namespace TreeNodeCollectionExtensions
{
    public static class TncExtensions
    {
        public static int Add(this TreeNodeCollection nodes, DRT.DRT_TvwNode_Abstract myTreeViewNode)
        {
            int newNodeIndex = nodes.Add(myTreeViewNode);

            //Do stuff to custom properties that are members of DRT_TvwNode_Abstract and classes derived from DRT_TvwNode_Abstract

            return newNodeIndex;
        }
    }
}

这样使用

using TreeNodeCollectionExtensions;

public class MyTreeView : MyTreeView_Abstract
{
    public MyTreeView() : base()
    {
    }

    public void CreateTree()
    {
        MyTreeViewNode myTreeViewNode;

        //Add node to root of TreeView 
        //Using named parameter to force the compiler to
        //use the Add extension method and not the base Add method
        myTreeViewNode = new MyTreeViewNode("root node text");
        Nodes.Add(myTreeViewNode: myTreeViewNode);

        //Add node one level below root node of TreeView
        //Using named parameter to force the compiler to
        //use the Add extension method and not the base Add method
        myTreeViewNode = new MyTreeViewNode("level 1 node text");
        int newLevel1NodeIndex = Nodes[0].Nodes.Add(myTreeViewNode: myTreeViewNode);

        //Add node one level below level 1 node just created 
        //Using named parameter to force the compiler to
        //use the Add extension method and not the base Add method
        myTreeViewNode = new MyTreeViewNode("level 2 node text");
        int newLevel2NodeIndex = Nodes[0].Nodes[newLevel1NodeIndex].Nodes.Add(myTreeViewNode: myTreeViewNode);

        //etc., etc.

    }
}

【讨论】:

  • this TreeNodeCollection nodes 这是您要添加到其中的节点集合。有第二个参数有什么意义?当您调用treeView1.Nodes.Add() 时,为什么要将另一个节点集合作为参数?您在扩展方法的第一个参数中有节点集合。
  • 我不确定您是否正确使用了扩展方法。扩展方法将向对象实例添加新方法,并且始终将该实例定义为方法的第一个参数。但是在调用扩展方法时,不需要将对象传递给方法。例如。假设您为字符串创建了一个Reverse 扩展方法:public static string Reverse (this string input),那么作为用法,这样调用它:someString.Reverse() 就足够了,无需传递实例。事实上someString 将作为input 传递给方法。
  • 你是对的 - 我嗯......很难理解这些东西。我在 80 年代开始担任开发人员(过程编程)。最近开始学习OOD//OOP 和C#。这已经/是一个挑战。我修复了我的更新。我想我现在拥有它
猜你喜欢
  • 1970-01-01
  • 2020-08-18
  • 2017-09-14
  • 2020-02-13
  • 1970-01-01
  • 2018-05-07
  • 2010-09-29
  • 1970-01-01
相关资源
最近更新 更多