더북(TheBook)

C# 8.0 버전의 새로운 기능 열 가지가 적용된 코드 작성하기

Program.cs 파일에 200줄 가까이 되는 다음 내용을 입력한 후 실행해 보세요.

C# 8.0 버전의 새로운 기능 열 가지: DotNet\SeeSharp.Eight\Program.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SeeSharp.Eight
{
    //인터페이스
    public interface IEmployee
    {
        public string Name { get; }
        public decimal Salary { get; }
        //[!] C# 8.0: Default interface members
        public string Id { get => $"{Name}[{this.GetHashCode()}]"; }
    }

    //클래스
    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 클래스
    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;

        //Deconstruct 메서드
        public void Deconstruct(out string name, out string topic)
            => (name, topic) = (Name, Topic);

        //인덱스 및 범위
        //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 병합 할당 연산자: ??=
            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);

        //ⓐ 동기 방식 출력
        foreach (var employee in Service.GetEmployees())
        {
            Print($"Name : {employee.Name}");
        }
        Print("========================================");
        foreach (var employee in Service.GetEmployees())
        {
            //패턴 매칭: C# 7.0
            if (employee is Administrator administrator
                && administrator.Department is "ABC")
            {
                Print($"Administrator : {administrator.Name}");
            }
        }
        Print("========================================");

        //ⓑ 비동기 방식 출력
        await foreach (var employee in Service.GetEmployeesAsync())
        {
            //패턴 매칭: C# 8.0 속성 패턴
            if (employee is Professor
            {
                Topic: "Computer Science", Name: var name
            } professor)
            {
                Print($"Professor : {name} ({professor.Id})");
            }
        }
        await foreach (var employee in Service.GetEmployeesAsync())
        {
            //패턴 매칭: C# 8.0 위치 패턴
            if (employee is Professor(var name, "Computer Science") professor)
            {
                Print($"Professor : {name} ({professor.Id})");
            }
        }

        //C# 8.0 - nullable 참조 형식
        var red = new Person("YJ", "Park");
        var length = GetMiddleNameLength(red);
        Console.WriteLine(length); //0

        //Switch 식
        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 { }
            if (person?.MiddleName is { } middle) return middle.Length;
            return 0;
        }
    }
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.