1. ホーム
  2. c#

C#でデリゲートを使う

2023-08-24 10:14:54

質問

C#言語と.NETフレームワークにおいて、デリゲートの理解について教えていただけないでしょうか。 私はいくつかのコードをチェックしようとしていて、私が受け取った結果が私にとって予期しないものであることがわかりました。それはここにあります。

class Program
{
    public static int I = 0;

    static Func<string> del = new Func<string>(I.ToString);

    static void Main(string[] args)
    {
        I = 10;
        Console.WriteLine("{0}", del());
    }
}

答えは0でしたが、10ではありませんでした。なぜですか?

どのように解決するのですか?

原因は以下の通りです。

デリゲートを宣言する方法によって、それは直接 ToString メソッドを指します。これは作成時にキャプチャされます。

flindebergが以下のコメントで指摘しているように、各デリゲートはターゲットとターゲット上で実行されるメソッドを持っています。

この場合、実行されるメソッドは明らかに ToString メソッドです。興味深いのは、このメソッドが実行されるインスタンスです。のインスタンスです。 I のインスタンスであり、これはデリゲートが I を使用して使用するインスタンスを取得するのではなく、インスタンス自体への参照を保存していることを意味します。

後で I を別の値に変更し、基本的に新しいインスタンスを代入します。この場合、デリゲートに取り込まれたインスタンスは魔法のように変化しませんが、なぜそうしなければならないのでしょうか?

期待する結果を得るには、デリゲートをこのように変更する必要があります。

static Func<string> del = new Func<string>(() => I.ToString());

このように、デリゲートは無名メソッドを指し示し、そのメソッドは ToString を実行します。 I を、デリゲート実行時に指定します。

この場合、実行されるメソッドはデリゲートが宣言されているクラスで作成された無名メソッドです。静的メソッドであるため、インスタンスはnullとなります。

コンパイラが生成した2番目のバージョンのデリゲートのコードを見てください。

private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
    return UserQuery.I.ToString();
}

見ての通り、通常のメソッドで行う 何か . この例では ToString の現在のインスタンスに対して I .