Isa@Diary

ソフトウェア開発やってます。プログラミングとか、US生活とかについて書きます。

ラムダ式のスコープ関連

特に何か特別なことがあるわけでもなくただのメモ。

Codes

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    public class IntegerWrapper
    {
        private int val { get; set; }

        public IntegerWrapper(int arg)
        {
            val = arg;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            DelegateTest delegateTest = new DelegateTest();

            //A variable that is captured will not be garbage-collected 
            //until the delegate that references it goes out of scope.
            delegateTest.TestMethod("internal");
            GC.Collect();

            //externalAct() still refers a local variable in TestMethod()
            delegateTest.externalAct();

            string str;
            delegateTest.TestMethod3(out str);

            IntegerWrapper iw = new IntegerWrapper(0);
            delegateTest.TestMethod4(ref iw);

            delegateTest.TestMethod5();
        }
    }

    public class DelegateTest
    {
        public Action externalAct;

        internal void TestMethod(string arg)
        {
            Action<string> internalAct;
            internalAct = new Action<string>((str) => Debug.WriteLine(str));
            internalAct(arg);

            string external = "external";
            externalAct = new Action(() => Debug.WriteLine(external));
        }

        internal void TestMethod2()
        {
            Func<int, int> func = (i =>
                {
                    int j = i + 2;
                    return j;
                });
            //Variables introduced within a lambda expression are 
            //not visible in the outer method.

            //int k = j;
        }

        internal void TestMethod3(out string str)
        {
            str = "TestMethod3 called";
            //A lambda expression cannot directly capture 
            //a ref or out parameter from an enclosing method.
            
            //Error: Cannot use ref or out parameter 'str' 
            //inside an anonymous method,
            //lambda expression, or query expression

            //Func<string, string> func = (arg => arg + str);
        }

        internal void TestMethod4(ref IntegerWrapper iw)
        {
            //A lambda expression cannot directly capture 
            //a ref or out parameter from an enclosing method.

            //Error: Cannot use ref or out parameter 'str' 
            //inside an anonymous method,
            //lambda expression, or query expression

            //Action act = () => iw.printValue();
        }

        internal void TestMethod5()
        {
            //A return statement in a lambda expression does not cause
            //the enclosing method to return.
            Action returnAct = () => { return; };
            returnAct();
            Debug.WriteLine("This line will be executed");
        }
    }
}