2009-04-17 4 views
12

私は彼らが言うれるreading this article about closuresしてきた:あなたは「 クロージャーには特別なものは何ですか?

  • 「ラッパークラスを作成」と「変数の寿命を延ばす」コンパイラ

    • は、「すべての配管は、自動で」

    など、.NETコンパイラはあなたのための配管の世話を

  • 「心配せずに、ローカル変数を使用することができますので、私は自分のコードにして私に基づいた例を作った、それはのように思えますクロージャは通常の名前付きメソッドと同様に動作しますが、「ローカル変数を気にせずに処理する」と「すべての配管は自動」です。

    この「ローカル変数のラッピング」は、クロージャを特別な/興味深い/有用なものにする問題を解決しましたか?

    using System; 
    namespace TestingLambda2872 
    { 
        class Program 
        { 
         static void Main(string[] args) 
         { 
          Func<int, int> AddToIt = AddToItClosure(); 
    
          Console.WriteLine("the result is {0}", AddToIt(3)); //returns 30 
          Console.ReadLine(); 
         } 
    
         public static Func<int, int> AddToItClosure() 
         { 
          int a = 27; 
          Func<int, int> func = s => s + a; 
          return func; 
         } 
        } 
    } 
    

    回答

    だから、この1への答えは、マルクが指摘Jon Skeet's article on closuresを読むことです。この記事では、C#でラムダ式に至るまでの進化を示すだけでなく、このトピックの優れた読解であるJavaでクロージャがどのように処理されるかを示しています。

  • +0

    他の言語(Javascriptなど)でクロージャをサポートしています。概念やC#の具体的な実装について質問していますか? – strager

    +1

    私はその例が閉鎖の力を理解するにはあまりにも単純だと思います。 –

    +0

    @strager:私は一般的なコンセプトを意味しています。私は、デリゲート、クロージャー、マップ、ラムダ、ラムダ式、ラムダツリー、無名関数、カリングなどの周りに頭を浮かべています。 Stackoverflowはあなたのタイトルが「不十分でユニークな単語を追加する」と言っているので、C#をタイトルに入れていたのですが、どの言語をも超えているように見える関数プログラミングのパラダイムが数学などに根付いています... ) –

    答えて

    20

    例は明確ではなく、通常のキャプチャの使用方法を示していません(キャプチャされるのはaです。これは常に3ですのであまり面白くありません)。閉鎖せずにそれを試して今

    List<Person> people = ... 
    string nameToFind = ... 
    Person found = people.Find(person => person.Name == nameToFind); 
    

    ;:

    このテキストブックの例(述語)を考えてみましょうあなたは私たちが怠惰であっても、より多くの作業を実行する必要があります。

    PersonFinder finder = new PersonFinder(); 
    finder.nameToFind = ... 
    Person found = people.Find(finder.IsMatch); 
    ... 
    class PersonFinder { 
        public string nameToFind; // a public field to mirror the C# capture 
        public bool IsMatch(Person person) { 
         return person.Name == nameToFind; 
        } 
    } 
    

    キャプチャアプローチが異なるスコープで変数の多くにさらに拡張 - 隠されている複雑さのたくさんを。

    上記の名前以外は、C#コンパイラが背後で何をしているのかを概算したものです。追加のスコープが含まれる場合、異なるキャプチャクラスの連鎖を開始します(つまり、内部スコープは外部スコープのキャプチャクラスへの参照を持ちます)。かなり複雑です。

    Jon Skeetは良いarticle on this here、さらにはin his bookです。

    +0

    (削除された質問に対して 'static'にする):いいえ - 異なるスレッドが同時に異なる名前を検索したり、デリゲートの実行を延期したりする可能性があるためです。 –

    +1

    +1のC#深度部分のクロージャ –

    +2

    +1この文の深さクロージャの記事: "クロージャを使用すると、ある種の動作をカプセル化し、他のオブジェクトと同様に渡し、コンテキストにアクセスできます。彼らは最初に宣言された " –

    0

    クロージャは、コンパイラの機能です。あなたはそれを見ることはできません。あなたが書いたコードを作成するだけです。

    AddToItClusure()のスコープ内のローカル変数a = 27を使用するため、AddToIt(3)の呼び出しは失敗します。この変数は、AddToItが呼び出されたときには存在しません。

    しかし、コンパイラによって使用されるメカニズムであるクロージャのために、コードは機能し、それについて気にする必要はありません。

    関連する問題