C# ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์™„๋ฒฝ ๊ฐ€์ด๋“œ

๋ชฉ์ฐจ

  1. ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ปฌ๋ ‰์…˜
  2. ๊ธฐ๋ณธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…
  3. ์Šค๋ ˆ๋”ฉ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ
  4. ๊ณ ๊ธ‰ ์Šค๋ ˆ๋”ฉ ๊ฐœ๋…
  5. Task์™€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  6. ํ˜„๋Œ€์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋Šฅ
  7. LINQ์™€ ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ

1. ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ปฌ๋ ‰์…˜

IEnumerable๊ณผ IEnumerator ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„

class Points : IEnumerable, IEnumerator
{
    List<Point> points = new List<Point>();
    int index = -1;

    public object Current => points[index];
    
    public IEnumerator GetEnumerator()
    {
        Reset();
        return this;
    }

    public bool MoveNext()
    {
        return ++index < points.Count;
    }
}

์ปฌ๋ ‰์…˜ ์ •๋ ฌ์„ ์œ„ํ•œ IComparer ๊ตฌํ˜„

class PointCompare : IComparer
{
    public int Compare(object x, object y)
    {
        Point a = (Point)x;
        Point b = (Point)y;
        return a.X - b.X;
    }
}

๊ฐ์ฒด ๋ณต์ œ๋ฅผ ์œ„ํ•œ ICloneable ๊ตฌํ˜„

class Point : ICloneable
{
    public object Clone()
    {
        return MemberwiseClone();  // ์–•์€ ๋ณต์‚ฌ
    }
    
    // ๋˜๋Š” ๊นŠ์€ ๋ณต์‚ฌ
    public Point Clone()
    {
        return new Point(X, Y);
    }
}

LINQ ํ™œ์šฉ

int[] arr = { 30, 56, 78, 45, 12, 99, 33 };
arr.OrderBy(v => v)
   .Where(v => v % 2 == 0)
   .ToList()
   .ForEach(v => Console.WriteLine(v));

์ฃผ์š” ํŠน์ง•

  • ์ปฌ๋ ‰์…˜์˜ ๋ฐ˜๋ณต ๋™์ž‘ ๊ตฌํ˜„ (IEnumerable/IEnumerator)
  • ์‚ฌ์šฉ์ž ์ •์˜ ์ •๋ ฌ ๊ตฌํ˜„ (IComparer)
  • ๊ฐ์ฒด ๋ณต์ œ ๋ฉ”์ปค๋‹ˆ์ฆ˜ (์–•์€ ๋ณต์‚ฌ/๊นŠ์€ ๋ณต์‚ฌ)
  • LINQ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
  • ์ฐธ์กฐ ํƒ€์ž…์˜ ๋ณต์‚ฌ์™€ ์ฐธ์กฐ ๋น„๊ต
  • yield return์„ ํ†ตํ•œ ์ดํ„ฐ๋ ˆ์ดํ„ฐ ๊ตฌํ˜„

2. ๊ธฐ๋ณธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์™€ ์ œ๋„ค๋ฆญ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ

// ๊ธฐ๋ณธ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์„ ์–ธ
delegate void PrintDel(int data);

// ์ œ๋„ค๋ฆญ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์‚ฌ์šฉ
Action<int> action = x => Console.WriteLine(x);
Func<int, int> func = x => x * x;

์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ์™€ ํด๋ž˜์Šค

// ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ
static void Print<T>(T data)
{
    Console.WriteLine($"data: {data}");
}

// ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค
class Stack<T>
{
    List<T> lt = new List<T>();
    public void Push(T data) { lt.Add(data); }
    public T Pop() { /* ... */ }
}

์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜(ref, out)

// ref ๋งค๊ฐœ๋ณ€์ˆ˜
static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

// out ๋งค๊ฐœ๋ณ€์ˆ˜
static void Add(int a, int b, out int result)
{
    result = a + b;
}

๋žŒ๋‹ค์‹๊ณผ ์ต๋ช… ํ•จ์ˆ˜

Func<int, int> del = a => a * a;
Action<int> print = x => Console.WriteLine(x);

์ปฌ๋ ‰์…˜๊ณผ ์ œ๋„ค๋ฆญ ์ปฌ๋ ‰์…˜

List<int> lt = new List<int>();
lt.Add(10);
lt.Add(20);
lt.Add(30);

3. ์Šค๋ ˆ๋”ฉ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ

๊ธฐ๋ณธ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๊ณผ ์‹คํ–‰

Thread t = new Thread(new ThreadStart(PrintInteger));
t.Start();

static void PrintID()
{
    Console.Write($"[{Thread.CurrentThread.ManagedThreadId}]");
}

๋ณ€์ˆ˜ ๊ณต์œ ์™€ ์Šค๋ ˆ๋“œ ์Šค์ฝ”ํ”„

// ์ง€์—ญ๋ณ€์ˆ˜ ๋ฒ„์ „ - ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ๋…๋ฆฝ์ ์ธ i๋ฅผ ๊ฐ€์ง
static void PrintInteger()
{
    for (int i = 0; i < 10; ++i) { ... }
}

// ์ „์—ญ๋ณ€์ˆ˜ ๋ฒ„์ „ - ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ i๋ฅผ ๊ณต์œ 
static int i;
static void PrintInteger()
{
    for (i = 0; i < 10; ++i) { ... }
}

์ด๋ฒคํŠธ ์‹œ์Šคํ…œ ๊ตฌํ˜„

class IndexEventArgs : EventArgs
{
    public int Index { get; set; }
    public int Data { get; set; }
}

class Server
{
    public event EventHandler<IndexEventArgs> TestEvent;
    
    public void PrintArray()
    {
        if (rand.Next(5) == 1)
            TestEvent(this, new IndexEventArgs(i, arr[i]));
    }
}

4. ๊ณ ๊ธ‰ ์Šค๋ ˆ๋”ฉ ๊ฐœ๋…

์Šค๋ ˆ๋“œ ๋™๊ธฐํ™”์™€ ๋ฝ

static int count = 0;
static object key = new object();

static void ThreadFunc(object param)
{
    for (int i = 0; i < 1_000_000; ++i)
        lock (key)  // ์ž„๊ณ„ ์˜์—ญ ๋ณดํ˜ธ
        {
            ++count;
        }
}

ํŒŒ๋ผ๋ฏธํ„ฐํ™”๋œ ์Šค๋ ˆ๋“œ

Thread t1 = new Thread(new ParameterizedThreadStart(ThreadFunc));
t1.Start("100");  // ๋ฌธ์ž์—ด ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ

์Šค๋ ˆ๋“œ ํƒ€์ž…๊ณผ ๋ฐ์ดํ„ฐ ๊ณต์œ 

class ThreadData
{
    public int Start { get; set; }
    public int End { get; set; }
    public DataResult DataResult { get; set; }
}

DataResult dr = new DataResult();
t1.Start(new ThreadData(1, 100, dr));
t2.Start(new ThreadData(101, 200, dr));

5. Task์™€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

Task์™€ async/await ํŒจํ„ด

static async Task<int> TotalInteger(int s, int e)
{
    await Task.Delay(1000);
    return await Task.Run(() => {
        int sum = 0;
        for (int i = s; i <= e; i++) 
            sum += i;
        return sum;
    });
}

Task<int> t1 = TotalInteger(1, 10);
await t1;  // ๋˜๋Š” Task.WaitAll(t1);

Task ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ์™€ ๋™๊ธฐํ™”

int sum = 0;
object key = new object();

Task[] tasks = new Task[10];
for (int i = 0; i < 10; ++i)
{
    tasks[i] = Task.Run(() => {
        lock (key) {
            sum += j;
        }
    });
}

Task.WaitAll(tasks);

Task ๋Œ€๊ธฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜

// ๊ฐœ๋ณ„ Task ๋Œ€๊ธฐ
t1.Wait();

// ์—ฌ๋Ÿฌ Task ๋™์‹œ ๋Œ€๊ธฐ
Task.WaitAll(t1, t2, t3);
Task waitTask = Task.WhenAll(t1, t2);

6. ํ˜„๋Œ€์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋Šฅ

LINQ์™€ ํ™•์žฅ ๋ฉ”์„œ๋“œ

static class MyClass
{
    public static void Print<T>(this IEnumerable<T> cont)
    {
        foreach (var item in cont)
            Console.Write($"{item} ");
        Console.WriteLine();
    }
}

// LINQ ์‚ฌ์šฉ
IEnumerable<int> subset = Enumerable.Range(1, 100);
subset.Where(v => v % 5 == 0)
      .OrderByDescending(v => v)
      .Select(v => v + 20)
      .Print();

๋žŒ๋‹ค์‹๊ณผ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ

Action f1 = () => { Console.WriteLine("Hello f1()"); };
Func<int, int, int> f3 = (a, b) => a + b;

// LINQ์—์„œ์˜ ๋žŒ๋‹ค
arr.Where(v => v % 2 == 0);

var์™€ ์ต๋ช… ํƒ€์ž…

// var ํ‚ค์›Œ๋“œ
var value = 100;

// ์ต๋ช… ํƒ€์ž…
var obj = new { A = 10, B = "Hello" };

7. LINQ์™€ ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ

LINQ ๊ธฐ๋ณธ ์—ฐ์‚ฐ์ž

// Skip๊ณผ Take
var subset = arr.Skip(5).Take(3);  // 5๊ฐœ ๊ฑด๋„ˆ๋›ฐ๊ณ  3๊ฐœ ์„ ํƒ

// Where์™€ Select
var query = arr.Where(x => x % 2 == 0)      // ์กฐ๊ฑด ํ•„ํ„ฐ๋ง
               .Select(x => x * 2);          // ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜

// ์ง‘๊ณ„ ํ•จ์ˆ˜
int count = arr.Count();
int max = arr.Max();
int min = arr.Min();

์ปฌ๋ ‰์…˜๊ณผ ๊ฐ์ฒด ์ฟผ๋ฆฌ

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Phone { get; set; }
}

// ๊ฐ์ฒด ์ปฌ๋ ‰์…˜ ์ฟผ๋ฆฌ
var result = lt.Where(person => person.Name.Contains("๊ธธ"))
               .Select(person => new { 
                   Index = index++, 
                   Age = person.Age 
               });

LINQ ์ฟผ๋ฆฌ ์ž‘์—…

  • ํ•„ํ„ฐ๋ง (Where)
  • ์ •๋ ฌ (OrderByDescending)
  • ๋ณ€ํ™˜ (Select)
  • ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ (Any, All, Contains)
  • ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ (Count, Sum, Max, Min)

์ฃผ์š” ํŠน์ง•

  • LINQ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ฟผ๋ฆฌ ๋ฐ ๋ณ€ํ™˜
  • async/await๋ฅผ ์‚ฌ์šฉํ•œ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  • ํ™•์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ๊ธฐ๋Šฅ ํ™•์žฅ
  • ๋žŒ๋‹ค์‹์„ ํ†ตํ•œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  • Parallel ํด๋ž˜์Šค๋ฅผ ํ†ตํ•œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ
  • Task๋ฅผ ์‚ฌ์šฉํ•œ ๋น„๋™๊ธฐ ์ž‘์—… ๊ด€๋ฆฌ
  • ์ปฌ๋ ‰์…˜๊ณผ ์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•œ ํƒ€์ž… ์•ˆ์ •์„ฑ