C# 8.0์ ์๋ก์ด ๊ธฐ๋ฅ
- ๋ํดํธ ์ธํฐํ์ด์ค ๋ฉค๋ฒ(Default Inteface Members)
- ํจํด ๋งค์นญ
- Nullable Reference Type
- ์ธ๋ฑ์ฑ๊ณผ ์ฌ๋ผ์ด์ฑ
- ๋น๋๊ธฐ ์คํธ๋ฆผ
- using ์ ์ธ
- ๋ ๋ณํฉ ํ ๋น์
- ๊ตฌ์กฐ์ฒด ์ฝ๊ธฐ ์ ์ฉ ๋ฉค๋ฒ
- ์ ์ ๋ก์ปฌ ํจ์
- ๋ฌธ์์ด ๋ณด๊ฐ ํ ํฐ๊ณผ @ ํ ํฐ ์์
- Unmanaged constructed type
https://www.csharpstudy.com/Latest/CS8-def-itf-mem.aspx
1. ๋ํดํธ ์ธํฐํ์ด์ค ๋ฉค๋ฒ(Default Inteface Members)
์ด์ ๋ฒ์ ์์๋ ์ธํฐํ์ด์ค๋ฅผ ํ๋ฒ ๋ฐฐํฌํ ํ ์์ ํ๋ฉด, ๊ธฐ์กด์ ๊ตฌํ๋ ๋ชจ๋ ํ์ ๋ค์ ์์ ํ์ง ์๋ ํ ํ์ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผฐ๋ค. ๋๊ตฌ๋ ๊ทธ ์ธํฐํ์ด์ค๋ฅผ ์ธ๋ถ์์ ์ฌ์ฉํ๋ค๋ฉด, ์์ ์ ๊ฑฐ์ ๋ถ๊ฐ๋ฅํ์๋ค. C# 8.0์์๋ ์ธํฐํ์ด์ค์ ์๋ก์ด ๋ฉค๋ฒ๋ฅผ ์ถ๊ฐํ๊ณ ์๋ก์ด ๋ฉค๋ฒ์ Body ๊ตฌํ ๋ถ๋ถ์ ์ถ๊ฐํ ์ ์๊ฒ ๋์๋ค. ์ด๋ ๊ฒ ์๋ก ์ถ๊ฐ๋ ์ธํฐํ์ด์ค ๋ฉค๋ฒ๋ ๋ํดํธ๋ก ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด ๊ตฌํ๋ ํ์ ๋ค์ด ์ ๋ฉค๋ฒ๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ๊ตฌํ๋์ง ์์ ๊ฒฝ์ฐ ์ด ๋ํดํธ ๊ตฌํ์ ์ฌ์ฉํ๊ฒ ๋๋ค.
- ์๋ก ๊ตฌํํ๋ ํด๋์ค๋ ๋ํดํธ ๋ฉค๋ฒ ๊ตฌํ์ ์ฌ์ฉํ์ง ์๊ณ ์ฌ์ ์ํ ์ ์๋ค.
- ์ธํฐํ์ด์ค์ ๋ํดํธ ๋ฉค๋ฒ ๊ตฌํ์ ์ก์ธ์ค ํ๊ธฐ ์ํด์๋ ์ธํฐํ์ด์ค๋ก ์บ์คํ ๋ ๋ณ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
// ILogger v1.0
public interface ILogger
{
void Log(string message);
}
// ILogger v2.0
public interface ILogger
{
void Log(string message);
// ์ถ๊ฐ๋ ๋ฉค๋ฒ
void Log(Exception ex) => Log(ex.Message);
void Log(string logType, string msg)
{
if (logType == "Error" || logType == "Warning" || logType == "Info")
{
Log($"{logType}: {msg}");
}
else
{
throw new ApplicationException("Invalid LogType");
}
}
}
class MyLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
Debug.WriteLine(message);
}
// ๋ํดํธ ๊ตฌํ์ ์ฌ์ฉํ์ง ์๊ณ ์๋ก ์ ์ํจ
public void Log(Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
2. ํจํด ๋งค์นญ
1) switch expression
๊ธฐ์กด switch ๋ฌธ(switch statement)์ case ๋ณ๋ก ๊ฐ์ ์ฒดํฌํ์ฌ ๋ถ๊ธฐํ์ง๋ง, switch ์(switch expression)์ ๊ธฐ์กด์ case ๋ธ๋ก๋ค์ ๋ณด๋ค ๊ฐ๊ฒฐํ๊ฒ ์์ผ๋ก ํํํ ๊ฒ์ด๋ค.
- switch ์์ switch ๋ฌธ๊ณผ ๋ฌ๋ฆฌ switch ์ ์์ ๋ณ์ ๋ช ์ ์ ๊ณ ๊ฐ case ๋ธ๋ก์ case, break, default ๋ฑ์ ์ฐ์ง ์๊ณ (ํจํด/๊ฐ) => (์์)๊ณผ ๊ฐ์ ์์ผ๋ก ํํํ๋ค.
static double GetArea(Shape shape)
{
// switch expression
double area = shape switch
{
null => 0, // null ์ฒดํฌ
Line _ => 0,
Rectangle r => r.Width * r.Height,
Circle c => Math.PI * c.Radius * c.Radius,
_ => throw new ArgumentException() // default์ ๊ฐ์ ๊ธฐ๋ฅ
};
return area;
}
2) ์์ฑ ํจํด(Property Pattern)
์์ฑ ํจํด(Property Pattern)์ ๊ฐ์ฒด์ ์์ฑ์ ์ฌ์ฉํ์ฌ ํจํด ๋งค์นญ์ ํ ์ ์๋๋ก ํ ๊ฒ์ด๋ค. ์์ฑ ํจํด์ ์ฌ์ฉํ๋ฉด ๋ณต์กํ switch ๋ฌธ์ ๋ณด๋ค ๊ฐ๊ฒฐํ๊ฒ switch ์์ผ๋ก ํํํ ์ ์๋ค.
public decimal CalcFee(Customer cust)
{
// Property Pattern
decimal fee = cust switch
{
{ IsSenior: true } => 10,
{ IsVeteran: true } => 12,
{ Level: "VIP" } => 5,
{ Level: "A", IsMinor: false} => 10,
_ => 20
};
return fee;
}
3) ํํ ํจํด(Tuple Pattern)
ํํ ํจํด(Tuple Pattern)์ ํ๋์ ๋ณ์๊ฐ ์๋ ์ฌ๋ฌ ๊ฐ์ ๋ณ์๋ค์ ๊ธฐ๋ฐํ ํจํด ๋งค์นญ์ ๋งํ๋ค.
static int GetCreditLimit(int creditScore, int debtLevel)
{
// Tuple Pattern
var credit = (creditScore, debtLevel) switch
{
(850, 0) => 200,
var (c, d) when c > 700 => 100,
var (c, d) when c > 600 && d < 50 => 80,
var (c, d) when c > 600 && d >= 50 => 60,
_ => 40
};
return credit;
}
static void Main(string[] args)
{
int creditPct = GetCreditLimit(650, 30);
Console.WriteLine(creditPct);
}
4) ์์น ํจํด(Positional pattern)
๋ง์ฝ ์ด๋ค ํ์ ์ด Deconstructor๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด, Deconstructor๋ก๋ถํฐ ๋ฆฌํด๋๋ ์์ฑ๋ค์ ๊ทธ ์์น์ ๋ฐ๋ผ ํจํด ๋งค์นญ์ ์ฌ์ฉํ ์ ์๋๋ฐ, ์ด๋ฅผ ์์น ํจํด(Positional pattern)์ด๋ผ ํ๋ค.
class Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) =>
(x, y) = (X, Y);
}
static string ์ฌ๋ถ๋ฉด(Point point)
{
// Positional pattern
string quad = point switch
{
(0, 0) => "์์ ",
var (x, y) when x > 0 && y > 0 => "1์ฌ๋ถ๋ฉด",
var (x, y) when x < 0 && y > 0 => "2์ฌ๋ถ๋ฉด",
var (x, y) when x < 0 && y < 0 => "3์ฌ๋ถ๋ฉด",
var (x, y) when x > 0 && y < 0 => "4์ฌ๋ถ๋ฉด",
var (_, _) => "X/Y์ถ",
_ => null
};
return quad;
}
static void Main(string[] args)
{
var p = new Point(-5, -2);
string q = ์ฌ๋ถ๋ฉด(p);
Console.WriteLine(q); // 3์ฌ๋ถ๋ฉด
}
5) ์ฌ๊ท ํจํด(Recursive pattern)
ํจํด์ ๋ค๋ฅธ ์๋ธ ํจํด(sub pattern)๋ค์ ํฌํจํ ์ ์๊ณ ํ ์๋ธ ํจํด์ ๋ด๋ถ์ ๋ ๋ค๋ฅธ ์๋ธ ํจํด๋ค์ ํฌํจํ ์ ์๋๋ฐ, ์ด๋ฌํ ๊ฒ์ ์ฌ๊ท ํจํด(Recursive pattern)์ด๋ผ ํ๋ค.
IEnumerable<string> GetStudents(List<Person> people)
{
foreach (var p in people)
{
// Recursive pattern
if (p is Student { Graduated: false, Name: string name })
{
yield return name;
}
}
}