C# 8.0의 새로운 기능 10가지 소개
소개
이번 실습 예제에서는 하나의 .NET Core 기반의 C# 프로젝트를 만들고 C# 8.0의 주요 특징 10가지를 모두 적용하는 예제를 만들어보겠습니다.
따라하기 0: .NET Core 7.0 기반의 C# 콘솔 프로젝트 생성하기
(1) SeeSharp.Eight
이름으로 .NET Core 7.0 이상으로 C# 콘솔 앱 프로젝트를 생성합니다.
(2) SeeSharp.Eight
프로젝트에 마우스 오른쪽 버튼을 클릭 후 [Edit Project File]
메뉴를 선택하여 csproj 파일의 편집 화면으로 들어갑니다.
(3) SeeSharp.Eight
파일의 여러 항목 중에서 <PropertyGroup>
섹션에 <Nullable>
항목이 enable
로 되어 있는지 확인 또는 없으면 다음 샘플 코드와 같이 추가합니다.
코드: SeeSharp.Eight.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
따라하기 1: C# 8.0의 새로운 기능 10가지가 적용된 코드 작성
200 줄 가까이되는 다음 코드는 작성 후 실행해보세요
좀 더 빠른 이해를 위해서 다음 경로에 미리보기 동영상을 올려두었습니다.
코드: DotNet\SeeSharp.Eight\Program.cs
//[?] C# 8.0의 새로운 기능 10가지
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SeeSharp.Eight
{
// Interface
public interface IEmployee
{
public string Name { get; }
public decimal Salary { get; }
//[!] C# 8.0: Default interface members
public string Id { get => $"{Name}[{this.GetHashCode()}]"; }
}
// Class
public class Person
{
#nullable disable
public string Name { get; }
public Person(string name) => Name = name;
//[!]
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
#nullable enable
public Person(string first, string last)
{
FirstName = first;
MiddleName = null;
LastName = last;
}
public Person(string first, string middle, string last)
{
FirstName = first;
MiddleName = middle;
LastName = last;
}
}
// Abstract Class
public abstract class Employee : Person, IEmployee
{
public Employee(string name, decimal salary)
: base(name) => Salary = salary;
public decimal Salary { get; protected set; }
}
public class Professor : Employee, IEmployee
{
public string Topic { get; }
public Professor(string name, decimal salary, string topic)
: base(name, salary) => Topic = topic;
// TODO: Deconstruct() Method => C# 7.0 User-Defined Types Deconstructing
public void Deconstruct(out string name, out string topic)
=> (name, topic) = (Name, Topic);
//[?] Indices and ranges
//public string Id => $"{Name}[{Topic[0..3]}]";
public string Id => $"{Name}[{Topic[..3]}~{Topic[^3..^0]}]";
}
public class Administrator : Employee
{
public string Department { get; }
public Administrator(string name, decimal salary, string department)
: base(name, salary) => Department = department;
}
public static class Service
{
#nullable disable
static Person[] people = null;
#nullable enable
static Service()
{
//[?] Null Coalescing Assignment Operator: ??=
people ??= new Person[]
{
new Professor("RedPlus", 1______000, "Computer Science"),
new Administrator("Taeyo", 2_000, "ABC"),
new Professor("Itist", 3_000, "Computer Science")
};
}
public static IEnumerable<IEmployee> GetEmployees()
{
foreach (var person in people)
{
if (person is IEmployee employee)
{
yield return employee;
}
}
}
//[?] C# 8.0 Asynchronous streams
public static async IAsyncEnumerable<IEmployee> GetEmployeesAsync()
{
foreach (var person in people)
{
await Task.Delay(500);
if (person is IEmployee employee) yield return employee;
}
}
}
class Program
{
static async Task Main(string[] args)
{
//[?] C# 8.0 - Static Local Function
static void Print(string message) => Console.WriteLine(message);
//[A] Synchronous
foreach (var employee in Service.GetEmployees())
{
Print($"Name: {employee.Name}");
}
Print("========================================");
foreach (var employee in Service.GetEmployees())
{
//[?] Pattern Matching: C# 7.0 Type Pattern
if (employee is Administrator administrator
&& administrator.Department is "ABC")
{
Print($"Administrator: {administrator.Name}");
}
}
Print("========================================");
//[B] Asynchronous
await foreach (var employee in Service.GetEmployeesAsync())
{
//[?] Pattern Matching: C# 8.0 Property Pattern, Var Pattern
if (employee is Professor
{
Topic: "Computer Science", Name: var name
} professor)
{
Print($"Professor: {name} ({professor.Id})");
}
}
await foreach (var employee in Service.GetEmployeesAsync())
{
//[?] Pattern Matching: C# 8.0 Location Pattern
if (employee is Professor(var name, "Computer Science") professor)
{
Print($"Professor: {name} ({professor.Id})");
}
}
//[?] C# 8.0 - Nullable Reference Type
var red = new Person("YJ", "Park");
var length = GetMiddleNameLength(red);
Console.WriteLine(length); // 0
//[?] Switch Expression
Print("========================================");
await foreach (var employee in Service.GetEmployeesAsync())
{
Console.WriteLine(GetDetails(employee));
}
static string GetDetails(IEmployee person)
{
return person switch
{
Professor p when p.Salary > 1_000 => $"{p.Name}-{p.Topic}-Big",
Professor p => @$"{p.Name} - {p.Topic}",
Administrator a => $"{a.Name} - {a.Department}",
_ => $@"Who are you?"
};
}
}
static int GetMiddleNameLength(Person? person)
{
//[?] is somthing
if (person?.MiddleName is { } middle) return middle.Length;
return 0; // is null
}
}
}
Name: RedPlus
Name: Taeyo
Name: Itist
========================================
Administrator: Taeyo
========================================
Professor: RedPlus (RedPlus[Com~nce])
Professor: Itist (Itist[Com~nce])
Professor: RedPlus (RedPlus[Com~nce])
Professor: Itist (Itist[Com~nce])
0
========================================
RedPlus - Computer Science
Taeyo - ABC
Itist-Computer Science-Big
C:\DotNet\DotNet\DotNet\SeeSharp.Eight\bin\Debug\netcoreapp3.0\SeeSharp.Eight.exe (process 30252) exited with code 0.
Press any key to close this window . . .
추천 자료: ASP.NET Core 인증 및 권한 부여
추천 자료: .NET Blazor에 대해 알아보시겠어요? .NET Blazor 알아보기를 확인해보세요!