C# 使用委托调用成员函数

C# calling member function with delegate

因为 this post 我创建了一个新问题以使我的问题更清楚。我有一个 class 和下一个 class 成员,所以会有一个 class 实例的菊花链。我的 class 中的函数调用链中的另一个成员函数或所有实例。

c++对这个问题有一个合理的解决方案。在 C# 中,我尝试了一个委托。我做了一个小程序来表达我的意思。

    class Program  {
        static void Main(string[] args)
        {
            DaisyChain TestClass = new DaisyChain(1);
            TestClass.AddClass(new DaisyChain(2));
            TestClass.AllprintID();
        }
    }

    class DaisyChain  {
        private int ClassID;
        private DaisyChain NextClass;

        public DaisyChain(int ID) {ClassID = ID; }

        public void AddClass(DaisyChain newClass) {
            if (NextClass == null) {
                NextClass = newClass;
            } else {
                NextClass.AddClass(newClass);
            }
        }
        public void AllprintID()  {
            DoForEach(this.printID);
        }

        public delegate void doFunc();
        public void DoForEach (doFunc aMemberFunc)  {
            aMemberFunc();
            if (NextClass != null) {
                NextClass.DoForEach(aMemberFunc);
            }
        }

        public void printID() {
            Console.WriteLine(ClassID);
        }
    };

这个例子不正确,因为 class 实例不是函数调用的一部分。

我可以向我的成员函数添加一个 class argumnet 并更改委托,

       public void printID(DaisyChain me) {
            Console.WriteLine(me.ClassID);
        }

但此后函数将是静态的,无法再以正常方式使用。 如果有其他解决方案,我会很高兴。

委托类型应该有一个额外的参数,因为你想在不同的对象上调用printID。您可以向 doFunc 添加一个,或者只使用内置的 Action<T> 委托类型。

public void DoForEach (Action<DaisyChain> aMemberFunc)  {
    aMemberFunc(this);
    if (NextClass != null) {
        NextClass.DoForEach(aMemberFunc);
    }
}

调用DoForEach时,您可以传递一个lambda表达式:

public void AllprintID()  {
    DoForEach(x => x.printID());
}

或者如果你出于某种原因真的喜欢方法组语法,写一个本地函数printID:

public void AllprintID()  {
    void PrintID(DaisyChain chain) {
        chain.PrintID();
    }
    DoForEach(PrintID);
}

// method names should start with a capital letter :)
public void PrintID() {
    Console.WriteLine(ClassID);
}

其他代码仍然可以像往常一样调用 PrintID - AllprintID 之外的代码甚至不会注意到本地函数。

您正在尝试重新发明轮子。检查文档中的 LinkedList and LinkedListNode。这是一个让你上路的例子:

    var daisyChain = new DaisyChain();
    daisyChain.Add(1);
    daisyChain.Add(2);

    class DaisyChain: LinkedList<DaisyChainLink>
    {
        public void Add(int id) => AddLast(new LinkedListNode<DaisyChainLink>(new DaisyChainLink(id)));

        public void Print()
        {
            var link = this.First;
            link?.Value.Print();
            while (null != link?.Next)
            {
                link = link.Next;
                link?.Value.Print();
            }
        }
    }

    class DaisyChainLink
    {
        public DaisyChainLink(int id)
        {
            Id = id;
        }
        
        public int Id { get; }

        public void Print() => Console.WriteLine(Id);
    }