-1

我试图在 C# 中学习委托和事件,我知道事件是委托的某种包装,委托是函数/方法的指针......

下面是我的代码,但是当我运行它时,什么都没有显示......可能是什么问题?

public class ClassHandler
{
    public delegate void DoProcesses();
    public event DoProcesses DoProcessesEvent;
}

public class Class1
{
    public void Func1()
    {
        Console.WriteLine("Class 1 doing function 1");
    }
    public void Func2()
    {
        Console.WriteLine("Class 1 doing function 2");
    }

}

public class Class2
{
    public void Func1()
    {
        Console.WriteLine("Class 2 doing function 1");
    }
    public void Func2()
    {
        Console.WriteLine("Class 2 doing function 2");
    }

}


class Program
{
    static void Main(string[] args)
    {
        Class1 cs1 = new Class1();
        Class2 cs2 = new Class2();
        ClassHandler main = new ClassHandler();
        main.DoProcessesEvent += new ClassHandler.DoProcesses(cs1.Func1);
        main.DoProcessesEvent += new ClassHandler.DoProcesses(cs1.Func2);
        main.DoProcessesEvent += new ClassHandler.DoProcesses(cs2.Func1);
        main.DoProcessesEvent += new ClassHandler.DoProcesses(cs2.Func2);
        main.DoProcessesEvent += new ClassHandler.DoProcesses(ff); // this line here is causing an error: An object reference is required for the non-static field, method, or property 'TryDelegatesAndEvents.Program.ff()'    

        Console.Read();
    }
    public void ff()
    {
        Console.WriteLine("gggg");
    }
}

更新:我如何引发事件以便它已经执行方法?

4

5 回答 5

4

这条线的问题:main.DoProcessesEvent += new ClassHandler.DoProcesses(ff)

那是因为您的方法ff()是非静态方法,您不能像从静态方法那样直接访问它。

将您的方法ff设为静态,或创建包含类的对象并为其分配一个实例。

评论:您没有看到任何内容的原因是因为您只是将它们绑定到一个事件DoProcessesEvent,但您没有在任何地方引发该事件。您只是定义事件的处理程序。

编辑: 将您的课程更改ClassHandler为:

public class ClassHandler
{
    public delegate void DoProcesses();
    public event DoProcesses DoProcessesEvent;

    public void OnDoProcessEvent()
    {
        if (DoProcessesEvent != null)
            DoProcessesEvent();
    }
}

在 Console.Read(); 之前的 Main 方法中 类型:

main.OnDoProcessEvent();

这将引发事件,它将从应用程序处理,并将为您提供以下输出。

Class 1 doing function 1
Class 1 doing function 2
Class 2 doing function 1
Class 2 doing function 2
gggg
于 2012-06-18T05:05:27.240 回答
1

更改main.DoProcessesEvent += new ClassHandler.DoProcesses(ff);main.DoProcessesEvent += new ClassHandler.DoProcesses(new Program().ff); 或使 ff 静态

于 2012-06-18T05:06:38.913 回答
1

好吧,由于以下行,它无法编译:

main.DoProcessesEvent += new ClassHandler.DoProcesses(ff); 

VS吐出的错误是:

An object reference is required for the non-static field, method, or property 'ConsoleApplication2.Program.ff()'

只需将您的 ff() 方法更改为静态即可绕过它。

例如:

public static void ff()
{
    Console.WriteLine("gggg");
}
于 2012-06-18T05:10:12.260 回答
0

除了前面评论中指出的问题外,您还必须触发事件。

在检查它是否为空并触发它之前制作一个事件的副本。这将消除线程在您检查 null 和触发事件之间的位置处事件变为 null 的潜在问题:

// Copy the event delegate before checking/calling

EventHandler copy = DoProcessesEvent ;  
if (copy != null)     
   copy(this, EventArgs.Empty); // Call any handlers on the copied list 

这将确保您的事件触发并且您将获得结果。

于 2012-06-18T05:17:02.910 回答
0

只是为了添加@Habib的答案,将实例类方法订阅为可能在另一个范围内的对象的事件处理程序是相当不寻常的(例如,如果 Class1 超出范围,但 main() 仍然有订阅会发生什么?)。更常见的情况是在同一范围内订阅(和取消订阅)处理程序,通常以异步方式(以下事件仍然同步引发)。

namespace ConsoleApplication1
{
    public delegate void ProcessCompletedEvent(string description);

    public class Class1
    {
        public void Func1()
        {
            // Do Func1 work
            Thread.Sleep(500);
            RaiseEvent("Func1 completed");
        }
        public void Func2()
        {
            // Do Func2 work
            Thread.Sleep(1000);
            RaiseEvent("Func2 completed");
        }
        private void RaiseEvent(string description)
        {
            if (ProcessCompleted != null)
            {
                ProcessCompleted(description);
            }
        }

        public event ProcessCompletedEvent ProcessCompleted;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Class1 cs1 = new Class1();

            // Wire up event handler
            cs1.ProcessCompleted += new ProcessCompletedEvent(MyHandler);

            cs1.Func1();
            cs1.Func2();

            Console.Read();
            // Remove the subscription
            cs1.ProcessCompleted -= MyHandler;
        }

        // *** Is in the same scope as main, which subscribes / desubscribes
        public static void MyHandler(string description)
        {
            Console.WriteLine(description);
        }
    }
}
于 2012-06-18T05:47:48.950 回答