-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を静的にするか、含まれているクラスのオブジェクトを作成して、メソッドにそのインスタンスを割り当てます。

コメントの場合: 何も表示されないのは、それらを event にバインドしているだけで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); 

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 に答える
1

ff を static に変更またはmain.DoProcessesEvent += new ClassHandler.DoProcesses(ff);作成するmain.DoProcessesEvent += new ClassHandler.DoProcesses(new Program().ff);

于 2012-06-18T05:06:38.913 に答える
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 に答える
0

以前のコメントで指摘された問題に加えて、イベントをトリガーする必要があります。

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 

これにより、イベントが確実に発生し、結果が得られます。

于 2012-06-18T05:17:02.910 に答える