簡體   English   中英

C#代表和事件

[英]c# delegates and events

我正在嘗試學習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");
    }
}

更新 :我如何引發事件,以便它將已經執行方法?

這行的問題: 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

更改main.DoProcessesEvent += new ClassHandler.DoProcesses(ff); main.DoProcessesEvent += new ClassHandler.DoProcesses(new Program().ff); 或將ff設為靜態

好吧,由於以下原因,它無法編譯:

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");
}

除了前面的注釋中指出的問題之外,您還必須觸發事件。

在檢查事件是否為null並將其觸發之前,請對其進行復制。 這將消除潛在的線程問題,即在檢查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 

這將確保您的事件能夠觸發,並且您將獲得結果。

僅添加到@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);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM