C# programming guide
C# ํ๋ก๊ทธ๋๋ฐ ์๋ฒฝ ๊ฐ์ด๋
๋ชฉ์ฐจ
- ์ธํฐํ์ด์ค์ ์ปฌ๋ ์
- ๊ธฐ๋ณธ ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋
- ์ค๋ ๋ฉ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ
- ๊ณ ๊ธ ์ค๋ ๋ฉ ๊ฐ๋
- Task์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ
- ํ๋์ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฅ
- 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๋ฅผ ์ฌ์ฉํ ๋น๋๊ธฐ ์์ ๊ด๋ฆฌ
- ์ปฌ๋ ์ ๊ณผ ์ ๋ค๋ฆญ์ ํ์ฉํ ํ์ ์์ ์ฑ