C# 9.0 새로운 기능 소개

참조

C# 9.0 개발 환경 구축

  • Visual Studio 2019
  • .NET CLI(.NET 5.0 SDK)
    • dotnet --version
    • dotnet --list-sdks
    • dotnet new console --help
    • dotnet new console -f net5.0
  • C# 프로젝트 속성에서 Application -> Target framework을 [+.NET 5+] 으로 설정해야 C# 9.0 기능 사용 가능합니다.

C# 9.0 추가된 기능들

  • 최상위 프로그램(Top-Level Programs)
  • init accessor
  • record Type
  • 향상된 패턴 매칭(Pattern matching)

최상위 프로그램 (Top-Level Programs)

1. 정의

  • C# 프로그램은 Main() 정적 메서드에서부터 프로그램 시작하며, C# 프로젝트 생성하면 항상 이 Main() 메서드를 자동으로 생성합니다.
  • 프로그래밍에서 이를 보통 엔트리 포인트(Entry point) 라 부릅니다.
  • 프로그래밍을 처음 시작하는 분들은 Main() 엔트리 포인트 부분의 이해가 어렵습니다.
  • 때문에 C# 9.0에서 이러한 제약을 없애고 바로 C# 문장을 사용할 수 있는 기능을 제공합니다.
  • 이를 최상위 프로그램(Top-Level Program) 이라 부릅니다.

2. 사용 예제

2.1. C# 9.0 Top-Level Program 적용 이전

using System;

namespace Csharp_9._0Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

2.2. C# 9.0 Top-Level Program 적용 이후

using static System.Console;

WriteLine("Hello World!");

2.3. Result (출력 결과)

  • Main() 메서드가 없어도, "Hello World!" 제대로 출력
  • Hello World!

1

init accessor

1. 정의

  • C# 9.0 에서 init 키워드가 새로 추가되었습니다.
  • init은 객체의 속성을 처음 초기화 하는 용도로 사용됩니다.
  • init 키워드는 해당 속성이 한번 설정되면, 그 이후에 변경할 수 없는 기능을 제공하여 Immutable(불변) 속성 만드는데 사용됩니다.

2. 사용 예제

2.1. 일반적인 속성 초기화 방법

  • 초기에 Sponsor 객체에서 DisplayName 속성을 Red 문자열로 초기화 진행
  • 그 다음에 DisplayName 속성을 RedPlus 문자열로 다시 저장 진행
  • 결과적으로 맨 마지막에 저장된 문자열인 RedPlus 문자열이 출력
var sponsor = new Sponsor //Sponsor 객체 생성
{
    Id = 1,
    DisplayName = "Red"
};

sponsor.DisplayName = "RedPlus"; //mutable(변경가능)

DisplayData(sponsor);

static void DisplayData(Sponsor sponsor) =>
    System.Console.WriteLine($"{sponsor.Id} - {sponsor.DisplayName}");

struct Sponsor
{
    public int Id { get; set; }
    public string DisplayName { get; set; }
}

2.2. 일반적인 속성 초기화 방법 Result (출력 결과)

2

2.3. init accessor 초기화 방법

  • 프로퍼티에서 set 대신 init 키워드 사용
  • 처음 객체 생성에서 초기화 진행 후, init 키워드로 설정된 속성을 다시 초기화 할 경우 에러 발생
  • 즉, init 키워드로 설정한 속성은 변경 불가합니다.
var sponsor = new Sponsor //Sponsor 객체 생성
{
    Id = 1,
    DisplayName = "Red"
};

//sponsor.DisplayName = "RedPlus"; //immutable(변경불가)

DisplayData(sponsor);

static void DisplayData(Sponsor sponsor) =>
    System.Console.WriteLine($"{sponsor.Id} - {sponsor.DisplayName}");

struct Sponsor
{
    public int Id { get; init; }
    public string DisplayName { get; init; } //init은 초기화 전용 Setter 입니다.
}

2.4. init accessor 초기화 방법 Result (출력 결과)

  • sponsor 객체 생성 후, DisplayName 속성에 처음 초기화 했던 Red 내용 출력
  • sponsor.DisplayName = "RedPlus"; 위처럼 다시 초기화 불가능

3

record Type

1. 정의

  • C# 9.0 에서 가장 두드러진 변화는 record 타입 을 새로 도입한 것입니다.
  • 지금까지는 C#/.NET 에서는 struct를 사용하는 Value Typeclass를 사용하는 Referecne Type 이 있었습니다.
  • C# 9.0 에서는 Immutable 값 데이터를 갖는 record 타입 을 추가하였습니다.
  • record 타입 은 객체 내의 멤버가 변하지 않는 Immutable Reference Type 을 만들기 위한 것 입니다.

2. 사용 예제

2.1. record Type 기본 사용 예제

  • 기존의 class 키워드 자리에 record 라는 타입의 Subscriber 생성
  • Subscriber 의 속성은 Title, Duration 2개의 속성을 갖습니다.
  • 2개의 속성 모두 init 속성으로 immutable 형태입니다.
var subscriber = new Subscriber { Title = "Visual", Duration = 2 };

System.Console.WriteLine(subscriber);

//Record 클래스 생성
record Subscriber
{
    public string Title { get; init; }
    public int Duration { get; init; }
}

2.2. record Type Result(출력 결과)

4

2.3. record Type 간편 구문 예제

  • record Subscriber(string Title, int Duration); 이와같이 Title, Duration 2개의 속성을 생성자 형태로 표현 가능합니다.
  • (1)과 (2)는 같은 구문입니다.
  • 다만 (2)번이 (1) 번 구문의 간편 구문으로서 사용법은 동일합니다.
//(1)
record Subscriber
{
    public string Title { get; init; }
    public int Duration { get; init; }
}

//(2)
record Subscriber(string Title, int Duration);
  • record Type 간편구문 예제
var subscriber= new Subscriber("Visual2", 3);

System.Console.WriteLine(subscriber);

//Record 타입 간편 구문(Syntax Sugar)  
record Subscriber(string Title, int Duration);

2.4. record Type 간편 구문 Result(출력 결과)

5

2.5. record Type with 표현식 예제

  • record Type은 immutable 형태로서 불변 상태를 나타냅니다.
  • 그러나 record Type을 변경하고 싶다면 with 키워드를 사용하면 됩니다.
var subscriber = new Subscriber { Title = "Visual", Duration = 2 };
var vip = subscriber with { Title = "VIP" }; // with 구문을 이용하면 record 클래스 속성 변경 가능


System.Console.WriteLine($"변경 전 출력");
System.Console.WriteLine(subscriber);

System.Console.WriteLine($"변경 후 출력");
System.Console.WriteLine(vip); //with 구문으로 Title = Visual -> VIP 로 변경

//record 타입 
record Subscriber
{
    public string Title { get; init; }
    public int Duration { get; init; }
}

2.6. record Type with 표현식 Result(출력 결과)

  • record Type으로 생성된 subscriber 객체를 하나 생성하여 Title = "Visual", Duration = 2 로 설정합니다.
  • vip 라는 객체 하나를 생성하고, 기존 subscriber 에서 Title 만 Visual -> VIP 로 변경을 시킵니다.
  • record 타입 내용 변경할 땐 with 키워드를 사용합니다.
  • 변경 전 subscriber 객체는 Title 이 "Visaul" 로 출력이 되고, vip 객체의 Title은 변경된 내용인 "VIP" 가 출력됩니다.

6

향상된 패턴 매칭(Pattern matching)

1. 정의

  • 패턴 매칭은 C# 6.0에서 처음 도입된 개념입니다.
  • C# 8.0 에서는 switch 식, 속성 패턴, 튜플 패턴, 위치 패턴, 재귀 패턴 등 다양한 기능이 추가되었습니다.
  • C# 9.0 에서는 부등호를 사용하여 비교 연산이 가능한 관계 패턴(Relation pattern), and, or, not 등과 같은 논리 패턴 (Logical pattern) , 단순 타입 패턴(Simple type pattern) 등이 새롭게 추가되었습니다.

2. 사용 예제

2.1. 관계 패턴(Relational pattern) 사용 예제

  • C# 9.0 에서는 switch 식에 >, <, >=, <= 등과 같은 관계 연산자를 사용할 수 있습니다.
  • 아래 예제는 GetGrade() 메서드에서 관계 연산자 패턴을 적용해 보았습니다.
// 관계 패턴 (Relational pattern)
//Student 객체 생성
Student stu = new Student() 
{ 
    Name = "홍길동",
    Score = 78
};

System.Console.WriteLine($"{stu.Name} 의 등급은 {GetGrade(stu)} 입니다.");

string GetGrade(Student stu)
{
    //관계패턴
    string grade = stu.Score switch
    {
        >= 90 => "A",
        >= 80 => "B",
        >= 70 => "C",
        >= 60 => "D",
        _ => "F",
    };

    return grade;
}

class Student
{
    public string Name { get; set; }
    public int Score { get; set; }
}

2.2. 관계 패턴(Relational pattern) 사용 예제 Result(출력 결과)

7

2.3. 논리 패턴(Logical pattern) 사용 예제

  • C# 9.0 에서는 switch 식에서 and, or, not 등과 같은 논리 연산자를 사용할 수 있습니다.
  • 관계 연산자와 논리 연산자는 혼합 해서 사용 가능합니다.
// 논리 패턴 (Logical pattern)
//Student 객체 생성
Student stu = new Student() 
{ 
    Name = "홍길동",
    Score = 94
};

Student stu2 = new Student()
{
    Name = "이순신",
    Score = 56
};

System.Console.WriteLine($"{stu.Name} 은 {GetValue(stu)} 입니다.");
System.Console.WriteLine($"{stu2.Name} 은 {GetValue(stu2)} 입니다.");

string GetValue(Student stu)
{
    //논리패턴 & 관계패턴 혼합
    string grade = stu.Score switch
    {
       > 79 and < 100 => "우등생",
       > 0 and < 60 => "나머지학생"
    };

    return grade;
}

class Student
{
    public string Name { get; set; }
    public int Score { get; set; }
}

2.4. 논리 패턴(Logical pattern) 사용 예제 Result(출력 결과)

8

2.5. 단순 타입 패턴(Simple type pattern) 사용 예제

  • switch 식에서 흔히 사용하지 않는 변수를 (_) 로 표시합니다.
  • 기존에는 이 밑줄(discard parameter 라고 부른다.)생각할 수 없었습니다.
  • C# 9.0에서는 생략이 가능합니다.
  • Check() 메서드에서 이전에는 그 외를 표시하려면 (_) 기호를 사용해야 했지만, C# 9.0 부터는 생략 가능합니다.
Duck \_duck = new Duck() { Name = "오리", Sound = "꽥꽥" };  
Dog \_dog = new Dog() { Name = "강아지", Sound = "멍멍" };

System.Console.WriteLine($"{\_dog.Name}는 {Check(\_dog)}");  
System.Console.WriteLine($"{\_duck.Name}는 {Check(\_duck)}");

string Check(Animal animal)  
{  
//논리패턴  
string result = animal switch  
{  
Dog d => "Dog",  
Cat c => "Cat",  
//Animal \_ => ""  
Animal => "그 외 동물들입니다."  
};


return result;


}

class Animal  
{  
public string Sound { get; set; }  
}

class Dog : Animal  
{  
public string Name { get; set; }  
}

class Cat : Animal  
{  
public string Name { get; set; }  
}

class Duck : Animal  
{  
public string Name { get; set; }  
}

2.6. 단순 타입 패턴(Simple type pattern) 사용 예제 Result(출력 결과)

9

728x90

이 글을 공유하기

댓글

Designed by JB FACTORY