지난 11월, 닷넷 8과 함께 C# 12가 여러 새로운 기능을 담고 출시됐다. 기본 생성자, 컬렉션 식, 인라인 배열 등의 새로운 기능은 더 간편하고 쉽게 더 효율적인 코드를 작성할 수 있게 해준다. 이전에 닷넷 8의 주요 특징을 둘러본 것과 마찬가지로 이번에는 C# 12의 중요한 새로운 기능에 대해 자세히 살펴보자.
ⓒ Getty Images Bank
여기에서 제공된 코드 예시를 사용하려면 비주얼 스튜디오 2022가 설치돼 있어야 한다. 아직 없다면 마이크로소프트 홈페이지에서 비주얼 스튜디오 2022를 다운로드할 수 있다.
비주얼 스튜디오에서 콘솔 애플리케이션 프로젝트 만들기
먼저 비주얼 스튜디오에서 닷넷 코어 콘솔 애플리케이션 프로젝트를 만든다. 비주얼 스튜디오 2022가 설치돼 있다면 아래의 단계에 따라 비주얼 스튜디오에서 새 닷넷 코어 콘솔 애플리케이션 프로젝트를 만들면 된다.
- 비주얼 스튜디오 IDE를 실행한다.
- “새 프로젝트 만들기”를 클릭한다.
- “새 프로젝트 만들기” 창에 표시되는 템플릿 목록에서 “콘솔 앱(.NET Core)”을 선택한다.
- 다음을 클릭한다.
- “새 프로젝트 구성” 창에서 새 프로젝트의 이름과 위치를 지정한다.
- 다음을 클릭한다.
- “추가 정보” 창이 표시되면 사용할 프레임워크 버전으로 “.NET 8.0(장기 지원)”을 선택한다.
- 만들기를 클릭한다.
이제부터는 이 닷넷 8 콘솔 애플리케이션 프로젝트를 사용하여 새로운 C# 12 기능을 살펴본다.
C# 12의 기본 생성자
기본 생성자는 C# 12의 새로운 기능으로, 형식 본문의 어디에서나 매개변수를 사용 가능한 생성자를 선언할 수 있게 해준다. 형식 선언과 함께 생성자를 선언할 있으므로 구문이 더 정확하고 간결해진다.
이제 모든 구조체 또는 클래스에서 기본 생성자를 만들 수 있다. 즉, 레코드 형식에서만 기본 생성자를 만들 수 있다는 제약이 더 이상 없다. 기본 생성자를 사용하면 별도의 생성자 정의가 더 이상 필요 없다.
다음 코드는 구조체 내에서 선언되는 기본 생성자를 보여준다.
public readonly struct Rectangle(double x, double y)
{
public readonly double Area { get; } = x * y;
}
기본 생성자는 일반적으로 다음과 같은 시나리오에서 사용된다.
- 멤버 또는 포함 형식의 필드를 초기화하기 위해
- base() 생성자 호출 시 인수로
- 포함 형식의 인스턴스 멤버에서 생성자 매개변수를 참조하기 위해
아래는 클래스 내에 선언된 기본 생성자의 간단한 구현이다.
public class Author(int Id, string firstName, string lastName)
{
public int Id { get; } = Id;
public string FirstName { get; } = firstName;
public string LastName { get; } = lastName;
public override string ToString()
=> $"Author Id: {Id}, First Name: {FirstName}, Last Name: {LastName}";
}
Author 클래스에서 ToString() 메서드가 오버라이드된 것을 볼 수 있다. 그 결과 기본 생성자로 매개변수를 전달해서 Author 클래스의 인스턴스를 만든 다음 이 인스턴스에서 ToString() 메서드를 호출해 속성 값을 표시할 수 있다. 이 부분은 아래 코드에서 볼 수 있다.
Author author = new Author(1, "Joydip", "Kanjilal");
Console.WriteLine(author.ToString());
C# 12의 컬렉션 식
C# 12 이전에는 List<int> 컬렉션을 초기화할 때 int[] 또는 Span<int>와 다른 구문을 사용해야 했다. C# 12에 컬렉션 식이 도입되면서 이제 배열, 목록, 사전과 같은 컬렉션을 만들 때 더 간결한 구문을 사용할 수 있다.
다양한 시나리오에서 컬렉션 식을 사용해 사전 정의된 값으로 컬렉션을 채우고, 여러 줄의 코드를 작성할 필요 없이 해당 요소로 직접 컬렉션을 초기화할 수 있다. 아래 예시에서는 컬렉션 식을 사용해 문자열 목록을 초기화한다.
List daysOfWeek = new() { "Sunday","Monday", "Tuesday","Wednesday", "Thursday", "Friday", "Saturday" };
위 코드에서는 컬렉션 식 { "Sunday","Monday", "Tuesday","Wednesday", "Thursday", "Friday", "Saturday" }를 사용해서 목록을 초기화한다. 컬렉션의 각 요소를 따로 추가하는 것보다 훨씬 더 간결하고 읽기 쉽다.
C# 12의 인라인 배열
인라인 배열은 고정된 크기의 구조체 기반 배열로, 버퍼를 관리할 때 코드의 효율성을 높이는 데 사용할 수 있다. 인라인 배열이 나오기 전에는 stackalloc 또는 포인터를 사용해서 메모리 블록을 조작할 수 있었지만 이를 위해서는 unsafe 키워드를 사용해서 어셈블리를 안전하지 않은 것으로 표시해야 했다. C# 12에서는 unsafe 키워드 없이 인라인 배열을 선언해서 메모리 블록을 다룰 수 있다.
C# 12에서 인라인 배열을 선언하는 방법은 다음과 같다.
[System.Runtime.CompilerServices.InlineArray(50)]
public struct Buffer
{
private int _element;
}
이제 C#의 다른 배열을 사용할 때와 거의 동일한 방법으로 인라인 배열을 사용할 수 있다.
C# 12의 기본 람다 매개변수
C# 12에서는 C#의 메서드 또는 로컬 함수를 사용할 때와 거의 같은 방식으로 람다 식에 기본 매개변수 값을 지정할 수 있다. 이 기능은 람다 식의 유연성과 표현력을 대폭 높여준다. 다음 코드는 C# 12에서 람다 식에 기본 매개변수 값을 지정하는 방법을 보여준다.
var AddIntegers = (int x, int y = 1) => x + y;
그런 다음 아래와 같이 람다 식을 호출할 수 있다.
Console.WriteLine(AddIntegers(10));
Console.WriteLine(AddIntegers(10, 5));
C# 12의 참조 읽기 전용 매개변수
참조 읽기 전용 매개변수는 C# 7.2부터 지원되기 시작했으며, 매개변수를 읽기 전용 컨텍스트의 참조로 전달해서 매개변수에 대한 수정을 막는 기능이다.
C# 12에서는 이 기능이 더 강화되어 다른 여러 시나리오에서도 참조 읽기 전용 매개변수를 사용할 수 있다. 매개변수 값을 수정하지 않고 해당 메모리 위치에만 액세스하려는 경우 메서드에서 참조 읽기 전용 매개변수를 사용해야 한다.
다음은 C# 12에서 참조 매개변수를 사용하는 방법의 예시다.
void Display(in int x, in int y)
{
Console.WriteLine($"The value of x is : {x}, the value of y is : {y}");
}
위 코드에서 Display 메서드는 x와 y를 모두 매개변수로 받는다. 메서드 매개변수에 사용된 in 키워드는 해당 매개변수는 수정할 수 없고 따라서 읽기 전용 참조로 전달된다는 것을 암시한다. 메서드에 큰 객체를 참조로 전달할 때 매개변수의 불변성을 보장하면서 불필요한 메서드 복사에 따른 비용을 피하고자 하는 경우 참조 읽기 전용 매개변수를 사용하면 된다.
C# 12의 인터셉터
C# 12에는 인터셉터라는 또 다른 흥미로운 기능이 포함된다. 인터셉터는 대체 메서드로 메서드 호출을 교체하거나 인터셉트할 수 있게 해준다. 이 기능을 사용하면 원본 코드를 변경하지 않으면서 메서드 호출 부분을 바꿀 수 있다.
인터셉터는 프리뷰 모드로 제공되는 실험적 기능이다. 즉, 앞으로 나올 C# 버전에서 변경될 수 있으므로 프로덕션 용도로는 권장되지 않는다. 인터셉터에 대한 더 자세한 내용은 기술 문서 페이지에서 볼 수 있다.
TargetFramework 닷넷 8
C# 12를 사용하려면 닷넷 8이 설치돼 있어야 한다. C# 12를 사용하도록 기존 프로젝트를 변경하려면 아래 코드와 같이 TargetFramework를 닷넷 8로 지정해야 한다.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
...
</PropertyGroup>
</Project>
editor@itworld.co.kr