第132回 クロージャーについて

公開日:2015-01-25 更新日:2019-05-11

1. 概要

独り言によるプログラミング講座、「第132回 クロージャーについて」です。

メソッド内で定義されたローカル変数は、メソッドを抜けると解放されて使用できなくなりますが、
そのローカル変数を参照するラムダ式や無名関数を戻り値として返した場合、
メソッドを抜けてもローカル変数は解放されずに保持されます。

2. 動画



3. 動画中に書いたソース

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //★独り言によるプログラミング講座

            //■クロージャーについて

            //・関数を変数に代入して使用する
            //  -> delegate、ラムダ式 -> 無名関数(匿名関数)
            //     クロージャー = 無名関数 ?

            //・関数内から外側のローカル変数を参照する

            //  -> 1つだけメソッドを持ったオブジェクト

            //  用途:コールバック

            /*
            //変数に関数を代入できる
            Test func = Abc;

            //関数の実行
            Abc("Test");
            func("Test");
            */

            /*
            //無名関数
            Test func = (delegate(string msg) {
                MessageBox.Show(msg);
            });

            func("Test");
            */

            /*
            Test func = ((msg) => {
                MessageBox.Show(msg + " ラムダ式");
            });

            func("Test");
            */

            /*
            int count = 0;

            //変数に関数を代入できる
            Action func = (() => {
                MessageBox.Show(count.ToString());
                count++;
            });

            //関数の実行
            func();
            func();
            func();
            */

            /*
            Action func = getAction();
            func(); //0
            func(); //1
            func(); //2

            Action func2 = getAction();
            func2(); //0
            func2(); //1
            func2(); //2
            */

            Action[] actList = new Action[10];

            //初期化
            /*
            for (int i = 0; i < 5; i++) {
                //変数に関数を代入できる
                actList[i] = (() => {
                    MessageBox.Show(i.ToString());
                });
            }*/
            /*
            int[] list = {0,1,2,3,4};
            list.Count(i => {
                actList[i] = (() => {
                    MessageBox.Show(i.ToString());
                });
                return true;
            });
            */
            
            Enumerable.Range(0, 10).Count(i => {
                actList[i] = (() => {
                    MessageBox.Show(i.ToString());
                });
                return true;
            });

            //実行
            for (int i = 0; i < 10; i++) {
                actList[i]();
            }

            this.Dispose();
        }

        public Action getAction() {
            int count = 0;

            //変数に関数を代入できる
            Action func = (() => {
                MessageBox.Show(count.ToString());
                count++;
            });

            return func;
        }

        //関数の型の定義  Test -> 型の名前
        public delegate void Test(string msg);

        //関数の本体
        public void Abc(string msg) {
            MessageBox.Show(msg);
        }
    }
}