본문으로 바로가기
제품데스크톱 도구TASTECAD도면 확인TASTEFILES파일 관리TASTEFTP파일 전송TASTESSH원격 작업공간TASTEZIP압축과 해제개발 도구TASTECODERust 통합 개발 환경TASTESTUDIO통합 개발·테스트 환경TASTEETL데이터 통합(ETL)서버TASTEREMOTE원격 데스크톱 서버TASTEGEO공간정보 서버TASTEMAIL메일 작업공간시작하기다운로드문서구매모든 제품
마켓플레이스
소식
개발소식오늘의 개발 소식개발 문서프로그래밍 언어RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron알고리즘알고리즘 기초알고리즘 핵심알고리즘 심화실무 알고리즘
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스커뮤니티 안내
협업기술 전수홈페이지 구축데스크톱 앱 구축릴리스·결제 파이프라인판매 파트너문의
서비스원격 데스크톱설치 패키지 커스텀
TASTEDEV
제품

데스크톱 도구

TASTECAD복잡한 도면을 가볍게 열다TASTEFILES필요한 파일만, 가장 빠르게TASTEFTP파일이 오가는 가장 단정한 길TASTESSH서버와 나 사이, 더 단단한 연결TASTEZIP더 빠르게 묶고, 더 안전하게 풀다

개발 도구

TASTECODERust 앱을 편집 · 빌드 · 디버깅 · 테스트까지 한 창에서TASTESTUDIO편집부터 원격 테스트와 승인 기반 AI 수정까지TASTEETL값을 보며 데이터를 옮깁니다

서버

TASTEREMOTE우리 회사 서버로 운영하는 원격 데스크톱TASTEGEOGeoServer 호환 공간정보 서버를 Rust로 다시 세웁니다TASTEMAIL메일의 주도권을 다시 내 손에

시작하기

다운로드모든 제품 최신 판문서제품 사용법구매구독 · 영구 라이선스모든 제품모든 제품 한눈에
모든 제품
마켓플레이스소식
개발

소식

오늘의 개발 소식언어 · 프레임워크 · GitHub · AI 공식 발표개발 문서언어 · 프레임워크 · 알고리즘 안내서

프로그래밍 언어

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

프레임워크

프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular
서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express
앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron

알고리즘

알고리즘 기초복잡도 분석 · 정렬 · 탐색 · 기본 자료구조 · 트리와 힙알고리즘 핵심그래프 탐색 · 최단 경로와 최소 신장 트리 · 동적 계획법 · 탐욕 알고리즘 · 분할 정복 · 백트래킹알고리즘 심화문자열 알고리즘 · 수학과 정수론 · 비트 연산 · 구간 트리 · 유니온 파인드실무 알고리즘코딩 면접 풀이 전략 · LRU 캐시 · 레이트 리미터 · 일관된 해시
개발 문서 전체 보기
커뮤니티
프로젝트빌더와 작업 발견개발 로그결정과 시행착오프롬프트재사용 가능한 지시AI 도구 이슈Claude · Codex · Gemini 문제와 우회법쇼케이스완성된 결과커뮤니티 안내공개하고 함께 만드는 방식
협업
기술 전수Rust·egui 네이티브 앱 만들기홈페이지 구축10개 언어, 계정, 문서·다운로드데스크톱 앱 구축Rust·egui, WebView 없이릴리스·결제 파이프라인서명 · MSI·deb·rpm·AppImage · 해시판매 파트너소개하고 결제액의 30% 받기문의구축 · 제휴 · 투자 문의
서비스
원격 데스크톱브라우저로 내 컴퓨터에 접속설치 패키지 커스텀필요한 기능만, 설정은 미리
구매
KO
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
로그인
로그인
TASTEDEV

작은 도구부터, 더 좋은 개발까지.

support@tastedev.netTASTEDEV 후원하기
제품제품군구매문서다운로드마켓플레이스고객 지원
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스
정책개인정보처리방침이용약관구독 약관환불 정책커뮤니티 운영 정책
계정로그인가입하기
방문자
오늘
012345678901234567890123456789012345678901234567890123456789
어제
012345678901234567890123456789012345678901234567890123456789
누적 조회
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
상호
지엑스소프트
대표자
최영구
사업자등록번호
853-44-00368
주소
인천광역시 미추홀구 경인로 351 9층 V24
전화
+82-10-4404-1523
이메일
whitecalvin@tastedev.net
개인정보 보호책임자
최영구

© 2026 TASTEDEV제품 정보는 현재 검증된 개발 소스를 기준으로 합니다.출시·고도화 중

C# 문서
C#
C# 시작하기기본 문법타입과 데이터프로젝트와 패키지오류 처리와 테스트핵심 개념: LINQ, 델리게이트, 비동기
토론

C# 안내서 · 6/6

핵심 개념: LINQ, 델리게이트, 비동기

C#을 C#답게 만드는 세 가지 기능이 있습니다. 함수를 값처럼 주고받는 델리게이트와 람다, 컬렉션을 선언적으로 다루는 LINQ, 그리고 기다리는 동안 스레드를 붙잡지 않는 async/await입니다. 세 기능은 서로 이어져 있어서 람다를 이해하면 LINQ가 읽히고, LINQ와 Task를 함께 쓰면 비동기 코드도 간결해집니다.

델리게이트와 람다

델리게이트는 메서드를 가리키는 타입 안전한 참조입니다. 직접 선언할 수도 있지만, 대부분은 기본 제공되는 Func<...>(값을 돌려줌)와 Action<...>(돌려주지 않음)을 씁니다. 람다 식 (매개변수) => 식은 이름 없는 메서드를 그 자리에서 만드는 문법입니다.

Func<int, int, int> add = (a, b) => a + b;
Func<string, bool> isLong = s => s.Length > 5;
Action<string> log = message => Console.WriteLine($"[로그] {message}");

Console.WriteLine(add(2, 3));          // 5
Console.WriteLine(isLong("TASTEDEV")); // True
log("시작합니다");

// 메서드를 인수로 받는 메서드
static List<int> Apply(List<int> items, Func<int, int> transform)
{
    var result = new List<int>();
    foreach (var item in items)
        result.Add(transform(item));
    return result;
}

var doubled = Apply([1, 2, 3], x => x * 2); // [2, 4, 6]

// 람다는 바깥 변수를 붙잡을(capture) 수 있습니다
int threshold = 10;
Func<int, bool> overThreshold = x => x > threshold;

이벤트도 델리게이트 위에 만들어진 기능입니다. button.Click += (sender, e) => ...처럼 +=로 처리기를 등록하는 코드가 바로 델리게이트에 람다를 더하는 모습입니다.

LINQ

LINQ(Language Integrated Query)는 배열, 리스트, 데이터베이스 등 여러 데이터 원본을 같은 방식으로 질의하는 기능입니다. System.Linq의 확장 메서드에 람다를 넘기는 메서드 구문이 가장 흔합니다.

List<Order> orders =
[
    new("하늘", "도서", 18_000m),
    new("바다", "전자", 320_000m),
    new("하늘", "전자", 45_000m),
    new("구름", "도서", 22_000m),
];

var bigOrders = orders
    .Where(o => o.Amount >= 20_000m)
    .OrderByDescending(o => o.Amount)
    .Select(o => $"{o.Customer}: {o.Amount:N0}원")
    .ToList();

var byCategory = orders
    .GroupBy(o => o.Category)
    .Select(g => new { Category = g.Key, Total = g.Sum(o => o.Amount), Count = g.Count() });

foreach (var row in byCategory)
    Console.WriteLine($"{row.Category}: {row.Count}건, {row.Total:N0}원");

bool anyExpensive = orders.Any(o => o.Amount > 100_000m);
var first = orders.FirstOrDefault(o => o.Customer == "구름");

record Order(string Customer, string Category, decimal Amount);

최상위 문이 있는 파일에서는 이처럼 타입 선언을 문장들 뒤에 둡니다. SQL을 닮은 쿼리 구문으로도 같은 일을 할 수 있으며, 컴파일러가 메서드 구문으로 바꿔 줍니다.

var query =
    from o in orders
    where o.Category == "도서"
    orderby o.Amount
    select o.Customer;

LINQ의 중요한 성질은 지연 실행입니다. Where나 Select는 질의를 정의할 뿐이고, foreach로 열거하거나 ToList, Count, First처럼 결과가 필요한 메서드를 부를 때 실제로 실행됩니다. 같은 질의를 여러 번 열거하면 매번 다시 계산되므로, 결과를 재사용할 때는 ToList()로 한 번 구체화해 둡니다.

async/await와 Task

파일 · 네트워크 · 데이터베이스 작업은 기다리는 시간이 대부분입니다. async 메서드는 await 지점에서 작업이 끝나기를 기다리는 동안 스레드를 돌려주고, 작업이 끝나면 그 다음 줄부터 이어서 실행합니다. 비동기 메서드는 결과가 없으면 Task를, 결과가 있으면 Task<T>를 돌려줍니다.

using var http = new HttpClient();

static async Task<int> GetLengthAsync(HttpClient client, string url, CancellationToken token)
{
    string body = await client.GetStringAsync(url, token);
    return body.Length;
}

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));

try
{
    // 하나씩 기다리기
    int length = await GetLengthAsync(http, "https://learn.microsoft.com", cts.Token);
    Console.WriteLine($"길이: {length}");

    // 여러 작업을 동시에 시작하고 모두 기다리기
    string[] urls = ["https://dotnet.microsoft.com", "https://www.nuget.org"];
    int[] lengths = await Task.WhenAll(urls.Select(u => GetLengthAsync(http, u, cts.Token)));
    Console.WriteLine(string.Join(", ", lengths));
}
catch (OperationCanceledException)
{
    Console.WriteLine("시간이 초과되어 취소했습니다.");
}

최상위 문에서는 await를 바로 쓸 수 있습니다. 비동기 코드를 쓸 때는 다음 규칙을 지키면 대부분의 문제를 피할 수 있습니다.

  • 비동기 메서드 이름은 Async로 끝내고, Task 또는 Task<T>를 돌려줍니다.
  • async void는 이벤트 처리기에서만 씁니다. 예외를 호출한 쪽에서 잡을 수 없기 때문입니다.
  • .Result나 .Wait()로 비동기 작업을 막아 세우지 말고 끝까지 await합니다. 교착 상태의 흔한 원인입니다.
  • 오래 걸리는 작업에는 CancellationToken을 받아 취소할 수 있게 합니다.
  • 서로 독립적인 작업은 Task.WhenAll로 동시에 진행합니다.

HttpClient는 요청마다 새로 만들지 않고 재사용하는 것이 권장됩니다. 웹 앱에서는 의존성 주입으로 IHttpClientFactory를 받아 쓰는 방법이 일반적입니다.

정리

  • Func와 Action 델리게이트에 람다를 담아 함수를 값처럼 넘기고, 람다는 바깥 변수를 붙잡을 수 있습니다.
  • LINQ는 Where, Select, GroupBy, OrderBy 같은 연산을 이어 붙여 데이터를 선언적으로 다루며, 결과가 필요할 때 실행됩니다.
  • async/await와 Task로 기다리는 동안 스레드를 막지 않는 코드를 쓰고, CancellationToken으로 취소를 지원합니다.

더 읽을거리

  • C# 문서: 언어 둘러보기, 자습서, 언어 참조를 모은 공식 문서입니다.
  • .NET 문서: 런타임, 라이브러리, dotnet 명령줄 도구 안내입니다.
  • LINQ 개요: 질의 구문과 표준 질의 연산자를 자세히 설명합니다.
  • 비동기 프로그래밍: async/await 모델과 작업 기반 패턴을 다룹니다.
  • .NET API 브라우저: 모든 기본 라이브러리 타입과 멤버를 찾아볼 수 있습니다.
  • NuGet 갤러리: 공개 패키지를 검색하고 정보를 확인합니다.
이 장에 대해 질문이 있나요?
이전 장오류 처리와 테스트

댓글 0개

인기 댓글순최신순

로그인 · 로그인하면 댓글을 남길 수 있습니다.