79

C#言語と.NET Frameworkで、デリゲートを理解するのを手伝ってもらえますか?いくつかのコードをチェックしようとしましたが、受け取った結果が予期しないものであることがわかりました。ここにあります:

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ではありませんでした。なぜですか。

4

5 に答える 5

79

その理由は次のとおりです。

ToStringデリゲートを宣言する方法は、静的intインスタンスのメソッドを直接指します。作成時にキャプチャされます。

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

于 2012-11-28T11:21:09.937 に答える
4

(関数が作成されたときではなく)適切な時間に実行できるIように、関数に渡す必要があります。I.ToString()

class Program
{
    public static int I = 0;

    static Func<int, string> del = num => num.ToString();

    static void Main(string[] args)
    {
        I = 10;
        Console.WriteLine("{0}", del(I));
    }
}
于 2012-11-28T11:23:51.457 に答える
1

これを行う方法は次のとおりです。

using System;

namespace ConsoleApplication1
{

    class Program
    {
        public static int I = 0;

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

        static void Main(string[] args)
        {
            I = 10;
            Console.WriteLine("{0}", del());
        }
    }
}
于 2012-11-28T11:24:30.690 に答える
0

C#デリゲートイネーブルは、オブジェクトとインスタンスの両方とメソッドをカプセル化します。デリゲート宣言は、System.Delegateクラスから派生したクラスを定義します。デリゲートインスタンスは、呼び出しリストをカプセル化します。呼び出しリストは、1つ以上のメソッドのリストであり、それぞれが呼び出し可能エンティティと呼ばれます。

詳細フォームを学ぶ

http://asp-net-by-parijat.blogspot.in/2015/08/what-is-delegates-in-c-how-to-declare.html

于 2015-08-24T10:57:00.833 に答える
-2

私の推測では、intは参照ではなく値によって渡されるため、デリゲートを作成するときは、現在の値「I」(0)のメソッドToStringへのデリゲートです。

于 2012-11-28T11:46:51.037 に答える