본문 바로가기

C#/이것이 C#이다

[ 이것이 C#이다 ] Chapter 14 . 람다식

 [ 학습 흐름 ]
  1. 람다식
  2. 문 형식의 람다식
  3. Func와 Action으로 더 간편하게 무명함수 만들기
  4. Func 대리자
  5. Action 대리자
  6. 식으로 이루어지는 멤버

[ 람다식의 기원 ]

[ 람다식 ]

- 람다식은 알론조 처지의 람다 계산법에서 사용하는 식이다 .

- 함수의 정의 / 변수 / 함수의 적용으로 이루어져 있는데 모든 것이 함수로 이루어져 있다 .

- 람다 계산법에서는 모든 것이 함수로 이루어져 있다 .


[ 람다식 ]

[ 람다식 ]

- 람다식은 익명 메소드를 만들기 위해 사용한다 .

- 람다식으로 만드는 익명 메소드는 무명 함수라는 이름으로 부른다 .

delegate int Calculate(int a,int b); //익명 메소드를 만들기 위한 대리자

static void Main(string[]args)
{
	//익명 메소드
	Calculate cal = delegate(int a,int b)
    {
    	return a+b;
    };
    
    //매개변수 목록=>식 (=>는 입력 연산자)
    Calculate cal1 = (int a,int b)=>a+b;
    //형식 유추 이용
    Calculate cal2 = (a,b)=>a+b;
}

 

- 람다식은 ( 매개변수 목록 / => / 계산코드 )로만 이루어진다 .

- 형식 유추의 기능으로 코드를 더욱 간결하게 만들 수 있다 .

- C# 2.0에서 익명 메소드가 도입되고 3.0에서 람다식이 도입되었다 .

using System;
using System.Data;
using System.Numerics;

namespace SimpleLamda;

class MainApp
{
    delegate int Calculate(int a, int b);
        
    static void Main(string[] args)
    {
        Calculate cal = (a, b) => a + b;
        Console.WriteLine($"{3}+{4} : {cal(3,4)}");
    }
}


[ 문 형식의 람다식 ]

- 문 형식의 람다식 역시 사용 가능하다 .

- 식 형식의 람다식은 반환 형식이 없는 무명함수를 만들 수 없지만 , 문 형식의 람다식은 가능하다 

using System;
using System.Data;
using System.Numerics;

namespace StatementLamda;

class MainApp
{
    delegate string Concatenate(string[] args);
        
    static void Main(string[] args)
    {
        Concatenate concat =
            (arr) =>
            {
                string result = "";
                foreach (string arg in args)
                {
                    result += arg;
                }
                return result;
            };
        Console.WriteLine(concat(args));
    }
}

 


[ Func 와 Action으로 더 간편하게 무명함수 만들기 ]

[ 람다식 ]

- 익명 메소드와 무명 함수는 코드를 간결하게 만들지만 , 매번 별개의 대리자를 선언해야 한다 .

- 이를 위해 .Net에서는 Func / Action 대리자를 미리 선언해두었다 .

- Func 대리자는 결과를 반환하는 메소드를 / Action 대리자는 결과를 반환하지 않는 메소드를 참조한다 .


[ Func 대리자 ]

- Func 대리자는 결과를 반환하는 메소드를 참조하기 위해 만들어졌다 .

- Func 대리자의 17가지 버전을 보면 형식 매개변수중 가장 마지막에 있는것이 반환 형식이다 .

- 입력 매개변수가 16개 이상 / ref out 한정자로 수식된 매개변수를 사용하는 경우가 아니면 별도의 대리자가 필요없다 .

//입력 매개변수가 없는 버전
Func<int>func 1 = ()=>10;
Console.WriteLine(func1());

//입력 매개변수가 하나
Func<int,int>func 2 = (x)=>x*2;
Console.WriteLine(func2(3));

//입력 매개변수가 둘
Func<int,int,int>func3 = (x,y)=>x+y;
Console.WriteLine(func#=3(2,3));

[ Action 대리자 ]

- Action 대리자는 반환 형식이 없다 .

- Func와 달리 어떤 결과를 반환하는 것을 목적으로 하는게 아닌,일련의 작업 수행이 목적이다 .

using System;
using System.Data;
using System.Numerics;

namespace ActionTest;

class MainApp
{
   
    static void Main(string[] args)
    {
        Action action1 = () => Console.WriteLine("Action()");
        action1();

        int result = 0;
        Action<int> action2 = (x) => result = x * x;
        action2(3);
        Console.WriteLine($"Result : {result}");

        Action<double, double> action3 = (x, y) =>
        {
            double pi = x / y;
            Console.WriteLine($"Action <T1,T2>({x},{y} : {pi})");
        };
        action3(22.0, 7.0);

    }
}

-


[ 식으로 이루어지는 멤버 ]

[ 트리 ]

- 메소드 / 인덱서 / 생성자 / 종료자는 클래스의 멤버로 본문이 중괄호 {}로 만들어져 있다 .

- 이러한 멤버의 본문을 식만으로 구현하는 것을 식 본문 멤버라고 한다 .

- 읽기 전용일때 생략 가능했던 get(set)키워드도 명시적으로 기술해야 한다 .

//메소드
public void Add(string name)=>list.Add(name);

//생성자
public FriendList()=>Console.WriteLine("생성자");

//종료자
~FriendList()=>Console.WriteLine("종료자");

//속성
public int Capacity
{
	get=>list.capacity;
    set=>list.Capacity=value;
}

//인덱서
public string this[int index]
{
	get=>list[index];
    set=>[list[inedx]=value];
}

 

using System;
using System.Collections.Generic;
using System.Data;
using System.Numerics;

namespace ExpressionBodiedMember;

class FriendList
{
    List<string>list = new List<string>();
    public void Add(string name) => list.Add(name);
    public void Remove(string name)=> list.Remove(name);    
    public void PrintAll()
    {
        foreach(var item in list)
            Console.WriteLine(item);
    }
    public FriendList() => Console.WriteLine("FriendList()");
    ~FriendList() => Console.WriteLine("~FriendList()");
    //public int Capacity=>list.Capacity; // 읽기 전용
    public int Capacity
    {
        get=>list.Capacity;
        set => list.Capacity = value;
    }
    //public string this[int index]=>list[index];   //읽기 전용
    public string this[int index]
    {
        get => list[index];
        set => list[index] = value;
    }

}

class MainApp
{
   
    static void Main(string[] args)
    {
        FriendList friendList = new FriendList();
        friendList.Add("Eeny");
        friendList.Add("Meeny");
        friendList.Add("Miny");
        friendList.Remove("Eeny");
        friendList.PrintAll();

        Console.WriteLine($"{friendList.Capacity}");
        friendList.Capacity = 10;
        Console.WriteLine($"{friendList.Capacity}");

        Console.WriteLine(friendList[0]);
        friendList[0] = "Moe";
        friendList.PrintAll();
    }
}