3

私は今までデリゲートを使用したことがなく、私の本のチュートリアルに従ってデリゲートを理解しようとしています。

これまでのところ、デリゲートは、呼び出しを行うデリゲートと同じ型オブジェクトを返し、同じオブジェクトでオーバーロードされるクラスのメソッドで使用できることを理解しました(間違っている場合は修正してください)。

私が取り組んでいるチュートリアルでは、次のコードが車のクラスに追加されています。

public delegate void CarEngineHandler(string msgForCaller);

private CarEngineHandler listOfHandlers;

public void RegisterWithCarEngine(CarEngineHandler methodToCall)
{
   listOfHandlers = methodToCall;
}

コンソールアプリではMain、次のコードが呼び出されます。

static void Main(string[] args)
{
    Car c1 = new Car("Slugbug", 100, 10);

    c1.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));

    Console.WriteLine("**** Speeding Up ******");
    for (int i = 0; i < 6; i++)
        c1.Accelerate(20);
    Console.ReadLine();
}

public static void OnCarEngineEvent(string msg)
{
    Console.WriteLine("\n***** Message From Car Object *****");
    Console.WriteLine("=> {0}", msg);
    Console.WriteLine("*************************************\n");
}

そして、ここにAccelerate方法があります:

public void Accelerate(int delta)
{
    if (carIsDead)
    {
        if (listOfHandlers != null)
            listOfHandlers("Sorry, this car is dead...");
    }
    else
    {
        CurrentSpeed += delta;

        if (10 == (MaxSpeed - CurrentSpeed) && listOfHandlers != null)
        {
            listOfHandlers("Careful buddy! Gunna Blow!");
        }
    }

    if (CurrentSpeed >= MaxSpeed)
        carIsDead = true;
    else
        Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
}

listofHandlersここで実際にどの程度正確に機能しているかについて、私は困惑していますか?これはどのコードのせいでもないことは知っていますが、デリゲートが実際にどのように機能するかについてもっと知りたいですか?それをチェックすることlistofHandlersnull私を失望させています...

4

4 に答える 4

11

デリゲートの定義

C# では、メソッドへのポインターを作成できます。このようなポインタは と呼ばれますDelegate。デリゲートは、メソッドを持つ通常のオブジェクトです。一致するパラメーターの型と一致する戻り値の型を持つメソッドのみを指すことができます。

delegate string MyHandler(int value1, string value2);

intパラメーターの型として ( , string) を持ち、 を返すメソッドを指すことができるデリゲート型を定義しますstring

このようなデリゲート (メソッドへのポインター) をフィールドに格納できます。

MyHandler myhandler;

このデリゲートは単なるオブジェクトなので、他のオブジェクトと同様にnull.

新しいデリゲートの作成

メソッドが与えられた場合:

string X(int v1, string v2) { /* ... */ }

そのメソッドを指す新しいデリゲートを作成できます。

myHandler = new MyHandler(X);

または、シンタックス シュガーのおかげで、次の短い構文を使用できます。

myHandler = X;

デリゲートの呼び出し

後でいつでも、デリゲートが指すメソッドを呼び出すことができます。

int i = 10;
string s = String.Empty;
string result = myHandler.Invoke(i, s);

または、再びシンタックス シュガーのおかげで:

int i = 10;
string s = String.Empty;
string result = myHandler(i, s);

もちろん、 にmyHandlerなる可能性がnullあるため、最初にそれを確認する必要がありますNullReferenceException。結局のところ、 でインスタンス メソッドを呼び出すことはできませんnull

myHandler = null;
myHandler.Invoke(10, "");

したがって、彼らはそれをチェックします:

string result;
if (myHandler != null)
    result = myHandler(i, s);

または、C# 6 ではほぼ同等です: ( isの場合にresultなることに注意してください。)nullmyHandlernull

string result = myHandler?.Invoke(i, s);

なぜ代表?

同じコードを使用して異なるメソッドを呼び出す場合は、呼び出されるメソッドを指すデリゲートをオブジェクトのパラメーターまたはフィールドとして渡すことができます。これが .NET でのイベントの実装方法であり、LINQ が機能する理由です。

于 2013-03-05T16:50:58.770 に答える
0

null チェックは、 を持っていない可能性があるためlistofHandlersですnull。の値を持つクラスのメソッドの呼び出しnullが違法であるのと同様に、デリゲートの呼び出しnullも許可されていません。

デリゲートは、メソッド呼び出しを抽象化する方法を提供します。Java では単一のメソッドを定義するインターフェイスを使用しますが、C# ではデリゲートを直接使用できます。

于 2013-03-05T16:21:31.450 に答える
0

listOfHandlersメソッドを除いて、参照変数のようなものです。

メソッドが含まれていない場合は、含まれているメソッドを呼び出したくないので、それが最初 listOfHandlersではないことを確認します。null

デリゲートは、nullまだメソッドが定義されていないデリゲートです。

于 2013-03-05T16:21:38.340 に答える
0

デリゲートは .Net の参照型であり、他のすべての参照型と同様にnull、開始する値で初期化されます。nullチェックは、まだ値に初期化されているかどうかを確認するだけです。リスナーがない場合、デリゲートを呼び出して報告するものは何もありません

于 2013-03-05T16:21:39.990 に答える