본문 바로가기
C#

C#] Delegates, Anonymous Methods and Lambda Expressions

by Fastlane 2022. 7. 18.
728x90
반응형
  • Delegates
  • Anonymous functions (Anonymous methods & Lambda expressions)

Delegates

    class Program
    {
        //Delegate defines the signature (return type and parameters)
        delegate void ArithmeticOperation(double operand1, double operand2);
    
        static void Addition(double number1, double number2)
        {
            Console.WriteLine($"{number1} + {number2} = {number1 + number2}");
        }
    
        public static int RunAnotherMethod(ArithmeticOperation theMethod, double operand1, double operand2)
        {
            return theMethod(a, b);
        }

        static void Main(string[] args)
        {
            //Create an instance of the delegate
            ArithmeticOperation sum = Addition;
            sum(10, 5);
            
            //Pass a delegate method as a variable
            RunAnotherMethod(sum, 10, 5)
        }
    }

델리게이트는 parameter와 return type과 함께 method의 참조를 나타낸다. 

  • parameter처럼 사용될 수 있다. 
  • reference type이며, method의 참조를 나타낸다. 
  • System.Delegate
  • delegate instance를 통해 함수 호출된다. 

 

Multicast delegate

+, - operator로 함수를 추가하거나 삭제할 수 있다. 

  • System.MulticastDelegate

 

 

Delegate의 발전

C# 1.0 delegate instance 생성

C# 2.0 anonymous method (inline statement blocks)

C# 3.0 lambda expressions (anonymous method와 비슷하나, 더 표현적이고 간결하다.)

 

Anonymous method

무명함수. delegate( ) { } 

delegate를 return한다. 

    class Program
    {    
        public static int RunAnotherMethod(Action<double,double> theMethod, double operand1, double operand2)
        {
            return theMethod(a, b);
        }

        static void Main(string[] args)
        {
            // Anonymous method is a delegate() {} and it returns a delegate
            Action<double,double> sum = delegate (double number1, double number2)
            {
                Console.WriteLine($"{number1} + {number2} = {number1 + number2}");
            };
            sum(10, 5);
            RunAnotherMethod(sum, 10, 5);
        }
    }

Lambda Expressions

object로 취급되는 code block이다. 

delegate, expression tree type을 만들 수 있는 짧은 형태의 무명함수이다. 

1) expression 


    class Program
    {    
        public static int RunAnotherMethod(Action<double,double> theMethod, double operand1, double operand2)
        {
            return theMethod(a, b);
        }

        static void Main(string[] args)
        {   
            // Lambda expressions are anything with => and a left/right value
            // They can return a delegate (so a method that can be invoked)
            // or an Expression of a delegate (so it can be compiled and then executed)
            Action<double,double> sum = (number1, number2) => Console.WriteLine($"{number1} + {number2} = {number1 + number2}");
            sum(10, 5);
            RunAnotherMethod(sum, 10, 5);
        }
    }

2) statement block

Action<double,double> sum = (number1, number2) => {
	Console.WriteLine($"{number1} + {number2} = {number1 + number2}");
};
sum(10, 5);

3) Expression of a delegate

Expression<Action<double,double>> sum = (number1, number2) => {
	Console.WriteLine($"{number1} + {number2} = {number1 + number2}");
};
sum.Compile().Invoke(10, 5);

LINQ query에서 사용될 수 있다. 

 

 

Another Example


    public static class Helpers
    {
        
        // extension method
        public static string GetFirstOrDefault(this List<string> items, Func<string, bool> findMatch)
        {
            foreach (var item in items)
            {
                if (findMatch(item))
                    return item;
            }

            return null;
        }
		
        // extension method generic version
        public static TResult GetFirstOrDefaultGeneric<TResult>(this List<TResult> items, Func<TResult, bool> findMatch)
        {
            foreach (var item in items)
            {
                if (findMatch(item))
                    return item;
            }

            return default(TResult);
        }
    }

    class Program
    {

        public delegate int Manipulate(int a);

        public static int NormalMethod(int a)
        {
            return a * 2;
        }

        public static int RunAnotherMethod(Manipulate theMethod, int a)
        {
            return theMethod(a);
        }

        public static int RunAnotherMethod(Func<int, int> theMethod, int a)
        {
            return theMethod(a);
        }

        static void Main(string[] args)
        {
            var normalMethodInvokeResult = NormalMethod(2);

            Manipulate normalMethodDelegate = new Manipulate(NormalMethod);
            int normalResult = normalMethodDelegate(3);
            int anotherResult = RunAnotherMethod(normalMethodDelegate, 4);

            Manipulate anonymousMethodDelegate = delegate (int a)
            {
                return a * 2;
            };
            int anonymousResult = anonymousMethodDelegate(3);
            int anotherResult2 = RunAnotherMethod(anonymousMethodDelegate, 4);

            Manipulate lambdaDelegate = (a) => a * 2;
            int lambdaResult = lambdaDelegate(3);
            int anotherResult3 = RunAnotherMethod(lambdaDelegate, 4);

            // Lambda can return Expression
            Expression<Manipulate> expressionLambda = a => a * 2;

            // A Func is a delegate with a return type
            // Replace Manipulate with a Func
            Func<int, int> funcDelegate = (a) => { return lambdaDelegate(a); };
            Func<int, int> func2Delegate = (a) => { return a * 2; };

            // Mimic the FirstOrDefault Linq expression
            var items = new List<string>(new[] { "a", "b", "c", "d", "e", "f", "g" });
            var itemInts = Enumerable.Range(0, 10).ToList();
            Func<string, bool> aa = item => { return item == "a"; };
            Func<int, bool> bb = itemInts => { return itemInts > 4; };

            // Calling the build in Linq FirstOrDefault
            var foundItem = items.FirstOrDefault(aa);
            var foundItemInt = itemInts.FirstOrDefault(bb);

            // Calling our version
            var foundItem2 = items.GetFirstOrDefault(aa);

            var foundItem3 = items.GetFirstOrDefaultGeneric<string>(aa);
            var foundItemInt3 = itemInts.GetFirstOrDefaultGeneric<int>(bb);
        }
    }
728x90
반응형

'C#' 카테고리의 다른 글

C#] LINQ - Projection  (0) 2022.07.20
C#] 반복자(Iterator), yield keyword  (0) 2022.07.19
C#] DynamicObject Class VS ExpandoObject Class  (0) 2022.07.07
C#] Expression trees 설명, Delegate와 차이점  (0) 2022.07.06
C#] Delegates  (0) 2022.07.06

댓글