언어/C, C++, C#

[ C# ] 람다함수

코딩은 내 밥줄 2022. 7. 3. 15:05

Delegate

= 메서드 번지를 저장하거나 다른 메서드의 인수로 메서드 자체를 전달하고 싶을 때 사용

  C++의 포인터와 비슷하다

  지정자 : 클래스에 소속되는 델리게이트일 때 지정자를 앞에 붙힌다

  형식 인수 이름을 꼭 붙여야된다 - int X , int num O

  클래스가 선언될 수 있는 모든 곳에 델리게이트 선언 가능하다

지정자 delegate 리턴타입 이름(인수목록)
delegate void deleA(int num)

  자체로 메서드를 가리킬 수 없어 인스턴스 생성 후 메서드를 가르키도록 초기화 해야됨

  → 특정 메서드를 가르킬땐 그 대상 메서드를 호출할 수 있다

delegate void dele(int a);

class Class4
{    
    public static void Meth1(int a) { Console.WriteLine("call 1" + a); }
    public static void Meth2(int a) { Console.WriteLine("call 2" + a); }

    public static void Main()
    {
        dele d;
        d = new dele(Meth1);
        d(12);
        d = new dele(Meth2);
        d(34);

        Console.ReadLine();
    }
}

dele 타입의 객체d를 선언하고 meth1, meth2을 가르키는 인스턴스를 각각만들었다

대입할 때 마다 매번 생성자를 호출하지만 참조되지 않는 인스턴스는 가비지 컬렉터가 알아서 지운다

C++ 의 포인터는 전역 메소드만 가리킬 수 있지만 델리게이트는 클래스에 속한 모든 메소드를 가리킬 수 있다

 

사용 목적 :  속도를 줄이고, 코드를 간결하게 하기위해서

델리게이트 사용하지 않을 때

 class Class5
{
    public static int Add(int a,int b) { return a + b; }
    public static int Mul(int a, int b) { return a * b; }

    public static void Main()
    {
        int a = 3; int b= 5;
        int o;
        Console.WriteLine("어떤 연산을 하고싶습니까? 1덧셈 2곱셈");
        o = Convert.ToInt32(Console.ReadLine());
        switch(o)
        {
            case 1:
                Console.WriteLine("결과 {0} 입니다", Add(a, b));
                break;
            case 2:
                Console.WriteLine("결과 {0} 입니다", Mul(a, b));
                break;
        }
    }

}

switch문과 같은 조건문을 작성할 때 속도가 느려지고 가독성이 좋지 않다

 

델리게이트 사용할 때

delegate int dele(int a, int b);

class Class6
{
    public static int Add(int a, int b) { return a + b; }
    public static int Mul(int a, int b) { return a * b; }

    public static void Main()
    {
        dele[] R = { Add, Mul };
        int a = 3; int b = 5;
        int o;
        Console.WriteLine("어떤 연산을 하고싶습니까? 1덧셈 2곱셈");
        o = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine("결과 {0} 입니다", R[o - 1](a, b));
        Console.ReadLine();
    }

}

객체 R에 두 메서드에 대한 참조를 저장하여 사용자로 부터 입력받은 첨자를 R에 바로 적용해 호출한다

 

 

익명 타입, 익명 함수

익명 타입 : 타입선언 후 객체 생성할 필요 없이 타입 정의, 객체 생성을 한번에 처리

var 객체 = new { p1=v1, p2=v2 };

 

목적: 한번만 사용할 타입를 생성할 때 사용하기 위해서

익명 타입 없이 타입 생성할 때

class human
{
    public string Name { get; set; }
    public human(string Name)
    {
        this.Name = Name;
    }


}

class Class1
{
    static void Main()
    {
        human H = new human("안녕");
        Console.WriteLine("이름 : "+ H.Name);
    }

}

익명타입으로 생성할 때

internal class Class3
{
    public static void Main()
    {

        var Lee = new { Name = "안녕" };
        Console.WriteLine("이름 : " + Lee.Name);
    }
}

class 또 생성하는 것을 줄일 수 있다

익명타입은 컴파일러에서 마음대로 이름을 붙이기 때문에 이 타입은 참조 할 수 없다

 

익명 함수 : 한번만 호출되는 메서드를 간결하게 델리게이트를 활용하여 사용

delegate(인수 목록) {메서드 코드};
delegate(int a ,b) {return a+b};

뒤에 꼭 세미콜론을 붙여야됨

 

목적 : 한번만 호출되는 메서드를 메서드를 만들지 않고도 사용하게 하기 위해서

익명 함수없이 생성할때 

delegate int dele(int a, int b);
class Class7
{
    public static int Add(int a, int b) { return a + b; }

    public static void Main()
    {

        dele d = Add;
        int k = d(2, 3);
        Console.WriteLine(k);

        Console.ReadLine();
    }
}

Add 메서드를 생성한 후 호출해야됨

 

익명함수를 사용할 때

delegate int dele(int a, int b);
class Class8
{

    public static void Main()
    {

        dele d = delegate (int a, int b) { return a + b; };
        int k = d(2, 3);
        Console.WriteLine(k);

        Console.ReadLine();
    }
}

Add메소드 생성 없이 바로 실행시킬 수 있다

 

 

 

람다함수

= 익명 메서드와 유사하지만 인수 타입을 생략할 수 있고, 표현식을 쓸 수 있고, 표현식을 트리로도 변환할 수 있다

익명함수 형식) delegate(int a){return a+1;};
람다함수 형식) a=> a + 1;

인수 타입은 위에 델리게이션 선언으로 a가 int인지 판별 가능하다

delegate 키워드가 사라지고 람다 표현식인 =>을 사용한다 뒤에는 return을 생략하고 실행 명령어를 입력한다

 

람다함수 예제

delegate int dele1(int a, int b);
delegate int dele2();
delegate void dele3();


class Class9
{
    public static void Main()
    {

        dele1 d1 = (x, y) => x + y;
        int b = d1(4, 5);
        Console.WriteLine(b);

        dele2 d2 = () => 1234;
        int c = d2();
        Console.WriteLine(c);

        dele3 d3 = () => { Console.WriteLine("안녕"); };
        d3();

        Console.ReadLine();
    }


}

목적 : delegate 키워드, 인수타입, return문등 형식을 맞추기 위해 번거로운 것들을 제거하여 익명 메서드를 압축한다