C#교과서 마스터하기 49. 함수와 함수형 프로그래밍 소개(LINQ)

min seung moon·2021년 7월 16일
0

C#

목록 보기
51/54

https://www.youtube.com/watch?v=z1ZM1A7fTW8&list=PLO56HZSjrPTB4NxAsEP8HRk6YKBDLbp7m&index=84

1. 함수와 함수형 프로그래밍 소개

01. 함수형 프로그래밍

  • 함수 형태로 계산을 진행하고 변경되는 변수 사용을 멀리하는 스타일
  • 생태값을 가지지 않는 함수들을 연속해서 호출해서 사용하는 개발 스타일

02. LINQ

  • Where()
  • Contains()
  • Count()
  • OrderBy()
  • OrderByDescending()
  • ThenBy()
  • ThenByDecending()
  • Skip()
  • Take()
  • ToList()
  • Select()
  • SelectMany()

2. 프로젝트(Functional)

  • 이전까지 작성한 JSON 파일 사용
[
  {
    "Id": 1,
    "Title": "ASP.NET Core",
    "IsDone": false
  },
  {
    "Id": 2,
    "Title": "Blazor",
    "IsDone": false
  },
  {
    "Id": 3,
    "Title": "C#",
    "IsDone": true
  },
  {
    "Id": 4,
    "Title": "Json",
    "IsDone": true
  },
  {
    "Id": 5,
    "Title": "Web API",
    "IsDone": false
  },
  {
    "Id": 6,
    "Title": "HttpClient",
    "IsDone": true
  },
  {
    "Id": 7,
    "Title": "LINQ",
    "IsDone": true
  }
]

01. 48까지의 프로젝트 사용 및 UI 폴더에 .NET Framework 빈 프로젝트 생성

  • TodoApp.WebApplication


02. TodoApp.WebApplication 프로젝트에 TodoList Web Form 추가


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TodoList.aspx.cs" Inherits="TodoApp.WebApplication.TodoList" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>할 일 목록</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <h1>할 일 목록</h1>
        </div>
    </form>
</body>
</html>
  • 오른쪽 클릭 -> 브라우저로 열기

03. GridView 추가(TodoList)

04. 참조 패키지 설치

  • System.Net.Http
  • Nettonsoft.Json

05. TodoList 코드 작성

  • api 서버 실행 후 실행
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 데이터 바인딩
                this.GridView1.DataSource = todos;
                this.GridView1.DataBind();
            }
        }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}



06. LINQ 사용

-1. SELECT 기본 출력

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }


    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}


-2. SELECT 다른 타입으로 변경 출력

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                      //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                // var q = todos.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}



-3. Where()로 조건절 추가

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                var query = todos.AsQueryable<Todo>(); // query 형태로 계속 출력하고 싶을 때
                query = query.Where(qr => qr.Id % 2 == 0); // 조건절 추가
                var q = query.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장
                

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}

-4. (조건처리)시간이 짝수일 때 짝수 홀수 일 때 홀수 번호의 게시물 출력

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                var query = todos.AsQueryable<Todo>(); // query 형태로 계속 출력하고 싶을 때

                // 조건 처리
                if(DateTime.Now.Second % 2 == 0)
                {
                    query = query.Where(qr => qr.Id % 2 == 0); // 조건절 추가(짝수)
                }else
                {
                    query = query.Where(qr => qr.Id % 2 != 0); // 조건절 추가(홀수)
                }
                
                
                var q = query.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장
                

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}


-5. (정렬 처리) Title 정렬

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                var query = todos.AsQueryable<Todo>(); // query 형태로 계속 출력하고 싶을 때

                // 조건 처리
                if(DateTime.Now.Second % 2 == 0)
                {
                    query = query.Where(qr => qr.Id % 2 == 0); // 조건절 추가(짝수)
                }else
                {
                    query = query.Where(qr => qr.Id % 2 != 0); // 조건절 추가(홀수)
                }

                // 정렬 처리
                const string sortOrder = "Title";                
                query = (sortOrder == "Title" ? query.OrderBy(it => it.Title) : query);
                
                var q = query.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장
                

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}

-6. (조건처리 추가) IsDone이 false만 출력

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                var query = todos.AsQueryable<Todo>(); // query 형태로 계속 출력하고 싶을 때

                // 조건 처리
                if(DateTime.Now.Second % 2 == 0)
                {
                    query = query.Where(qr => qr.Id % 2 == 0); // 조건절 추가(짝수)
                }else
                {
                    query = query.Where(qr => qr.Id % 2 != 0); // 조건절 추가(홀수)
                }

                // 조건처리
                query = query.Where(it => it.IsDone == false);

                // 정렬 처리
                const string sortOrder = "Title";                
                query = (sortOrder == "Title" ? query.OrderBy(it => it.Title) : query);
                
                var q = query.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장
                

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}

-7. GridView 추가

-8. GridView2에 메서드 체이닝하여 출력

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TodoApp.WebApplication
{
    public partial class TodoList : System.Web.UI.Page
    {

        protected void Page_Load(object sender, EventArgs e)
        {
           DisplayData();
        }

        private void DisplayData()
        {
            string url = "https://localhost:5001/api/Todos";

            using (var client = new HttpClient())
            {
                // 데이터 전송
                var json = JsonConvert.SerializeObject(new Todo { Title = "HttpClient", IsDone = true });
                var post = new StringContent(json, Encoding.UTF8, "application/json");

                client.PostAsync(url, post).Wait();

                // 데이터 수신
                var response = client.GetAsync(url).Result;
                var result = response.Content.ReadAsStringAsync().Result;
                var todos = JsonConvert.DeserializeObject<List<Todo>>(result);
                foreach (var item in todos)
                {
                    Console.WriteLine($"{item.Id} - {item.Title}({item.IsDone})");
                }

                // 필터링 : LINQ로 함수형 프로그래밍 스타일 구현
                // Select() : map()
                // var q = from todo in todos
                // select todo; // todos.Select(t => t); 랑 동일
                // IEnumerable<Todo> q = todos.Select(t => t); // 여기까지는 내용은 동일
                // var q = from todo in todos
                //  select new TodoViewModel { Title = todo.Title, IsDone = todo.IsDone };
                var query = todos.AsQueryable<Todo>(); // query 형태로 계속 출력하고 싶을 때

                // 조건 처리
                if(DateTime.Now.Second % 2 == 0)
                {
                    query = query.Where(qr => qr.Id % 2 == 0); // 조건절 추가(짝수)
                }else
                {
                    query = query.Where(qr => qr.Id % 2 != 0); // 조건절 추가(홀수)
                }

                // 조건처리
                query = query.Where(it => it.IsDone == false);

                // 정렬 처리
                const string sortOrder = "Title";                
                query = (sortOrder == "Title" ? query.OrderBy(it => it.Title) : query);
                
                var q = query.Select(t => new TodoViewModel { Title = t.Title, IsDone = t.IsDone}); // Todo 타입을  새로운 TodoViewModel로 맵핑해서 q에 저장
                

                // 데이터 바인딩
                this.GridView1.DataSource = q;
                this.GridView1.DataBind();

                this.GridView2.DataSource = todos.Where(t => t.Id % 2 == 1 && t.IsDone == false)
                    .OrderByDescending(t => t.Title)
                    .Select(t => new { 제목 = t.Title , 완료여부 = t.IsDone})
                    .ToList();
                this.GridView2.DataBind();
            }
        }
    }

    public class TodoViewModel
    {

        public string Title { get; set; }
        public bool IsDone { get; set; }
    }

    public class Todo
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
}

profile
아직까지는 코린이!

0개의 댓글