ko id ko ko ko ko es en en en ko ko ko ko en ko ko ko ko ko en ko ko ko ko ko fa ko ko ko ko ko ko ko ko en ko ko ko ko ko en ko ko ko ko ko fa ko ko ko ko ko ko ko ko en ko ko en en ko en ko ko ko en ko ru ko ko ko ko ko en en ko ko ko ko ko ko en en ko ko ko ko ko ko ko en ko ko en ko ko en ko en ko en en ko en en ko en en ko ko en ko fa ko en en ko ko ko ko ko en ko ko ko ko ko ko ko ko en ko ko ko ko ko ko ko ko en en ko en en en
파일 로컬 타입 (File-local Types)
정적 추상 멤버 (DIM for Static Members)
부호 없는 오른쪽 시프트 연산자 (Unsigned right shift operator)
UTF8 문자열 리터럴 (Utf8 String Literals)
ReadOnlySpan 의 패턴 매칭 (Pattern matching on ReadOnlySpan )
자동 기본 구조체 (auto-default structs)
보간의 개행 (Newlines in interpolations)
원시 문자열 리터럴 (Raw string literals)
정적 메소드 그룹에 대한 캐시 대리자 (Cache delegates for static method group)
시프트 연산자의 제약 완화 (Relaxing Shift Operator)
.NET 7이 미리보기 릴리스가 종료되면서 C# 11 기능이 확정되었습니다. 이에 따라 C# 11 기능을 대해 정리합니다.
새롭게 추가된 C# 11의 기능은 다음과 같습니다.
File-local Types (파일 로컬 타입)
DIM for Static Members (정적 추상 멤버)
Unsigned right shift operator (부호 없는 오른쪽 시프트 연산자)
Utf8 String Literals (UTF8 문자열 리터럴)
Pattern matching on ReadOnlySpan  (ReadOnlySpan 의 패턴 매칭)
Checked Operators (checked 연산자)
auto-default structs (자동 기본 구조체)
Newlines in interpolations (보간의 개행)
List patterns (목록 패턴)
Raw string literals (원시 문자열 리터럴)
Cache delegates for static method group (정적 메소드 그룹에 대한 캐시 대리자)
Relaxing Shift Operator (시프트 연산자의 제약 완화)
Generic attributes (제네릭 특성)
파일 로컬 타입 (File-local Types)
파일 내에서만 유효한 타입을 정의할 수 있습니다.
// FileLocalType.cs file class FileLocalType { } // Program.cs var s = new FileLocalType(); // 오류 CS0246 'FileLocalType' 형식 또는 네임스페이스 이름을 찾을 수 없습니다. using 지시문 또는 어셈블리 참조가 있는지 확인하세요.
ref 필드 (ref fields)
Span 의 ref 필드 _reference 처럼
public readonly ref struct Span  { ///  A byref or a native ptr.  internal readonly ref T _reference; ///  The number of elements this Span contains.  private readonly int _length; ...
이제 일반 개발자도 ref 필드를 만들 수 있게 되었습니다.
ref 필드는 스택 공간에만 존재할 수 있으므로 ref struct에서만 사용할 수 있습니다.
ref struct Vector2D { public ref int X; public ref int Y; }
required 멤버 (Required members)
이제 required 키워드로 필수 멤버를 만들 수 있습니다.
public class User { public required string Name { get; init; } public required int Age { get; init; } }
var user1 = new User(); // 오류 CS9035 필수 구성원 'User.Age'은(는) 개체 이니셜라이저 또는 특성 생성자에서 설정해야 합니다. // 오류 CS9035 필수 구성원 'User.Name'은(는) 개체 이니셜라이저 또는 특성 생성자에서 설정해야 합니다. var user2 = new User { Name = "dimohy", Age = 45 };
정적 추상 멤버 (DIM for Static Members)
이제 정적 속성 및 메소드 역시 인터페이스로 구현을 강제할 수 있습니다.
public interface IValue  { static abstract T Empty { get; } } public class NumValue : IValue  { public static NumValue Empty { get; } = new(0); private int _value; public NumValue(int value) => _value = value; }
이를 통해 이제 제네릭 형식 제약 조건 where를 이용해 정적 속성 및 메소드를 사용하는 기능을 구현할 수 있습니다.
var emptyValue = GetEmptyValue(new NumValue(100)); T GetEmptyValue (T value) where T : IValue  { return T.Empty; }
숫자 IntPtr (Numberic IntPtr)
IntPtr/UIntPtr과 플랫폼 의존적인 정수 타입 nint / nuint이 플랫폼 의존적인 동일한 정수형 데이터 값임에도 불구하고 다르게 취급되어 정수형에서 제공하는 연산을 제공하지 않았습니다.
이제 두 타입은 동일한 타입으로 처리됩니다. 즉, nint와 nuint는 IntPtr과 UIntPtr의 alias이고 동일한 타입이 됩니다.
부호 없는 오른쪽 시프트 연산자 (Unsigned right shift operator)
Java에도 존재하는 uinsiged right shift 연산자를 이제 C#에서도 제공합니다.
int n = -2020987651; // 0b10000111100010100010110011111101 Console.WriteLine($"[n] \t\t {Convert.ToString(n, 2).PadLeft(32, '0')}"); Console.WriteLine($"[n] >>> 4 ==> \t {Convert.ToString(n >>> 4, 2).PadLeft(32, '0')}"); Console.WriteLine($"[n] >> 4 ==> \t {Convert.ToString(n >> 4, 2).PadLeft(32, '0')}");
[n] 10000111100010100010110011111101 [n] >>> 4 ==> 00001000011110001010001011001111 [n] >> 4 ==> 11111000011110001010001011001111
UTF8 문자열 리터럴 (Utf8 String Literals)
이제 u8 접미사를 통해 UTF8 문자열 리터럴을 만들 수 있습니다.
ReadOnlySpan  utf8Text = "디모이"u8; // 또는 var utf8Text = "디모이"u8;
UTF8 문자열 리터럴은 ReadOnlySpan  타입이므로 일반 문자열 리터럴 처럼 상수로 취급되지는 않습니다. 또한 ReadOnlySpan  타입이 스택에만 존재할 수 있으므로 비동기 메서드에서 사용할 수 없는 제약이 존재합니다.
ReadOnlySpan 의 패턴 매칭 (Pattern matching on ReadOnlySpan )
이제 패턴 매칭에서 ReadOnlySpan 를 문자열과 매칭시킬 수 있습니다.
ReadOnlySpan  text = "디모이"; switch (text) { case "디모이": break; default: break; }
checked 연산자 (Checked Operators)
이제 overflow 제어에 필요한 checked/unchecked 동작을 직접 처리할 수 있게 됩니다.
// 출처 - 성태의 닷넷 이야기 public static Int3 operator checked ++(Int3 lhs) { if (lhs.value + 1 > 8388607) { throw new OverflowException((lhs.value + 1).ToString()); } return new Int3(lhs.value + 1); } public static Int3 operator ++(Int3 lhs) => new Int3(lhs.value + 1);
자동 기본 구조체 (auto-default structs)
이제 구조체에서 필드를 초기화 하지 않아도 자동으로 default으로 초기화 됩니다.
// C# 11 이전에는 초기화 관련 오류 발생 public struct S { public int x, y; public S() { } }
보간의 개행 (Newlines in interpolations)
이제 보간에서 개행이 가능합니다.
var v = $"Count is\t: { this.Is.A.Really() .That.I.Should( be + able)[ to.Wrap()] }.";
목록 패턴 (List patterns)
이제 목록 패턴이 지원됩니다.
int[] arr = { 1, 2, 3, 4, 5, 6 }; var result = arr switch { //[1, .., 6] => 1, [1, .., 5, _] => 2, _ => 0 }; Console.WriteLine(result);
원시 문자열 리터럴 (Raw string literals)
이제 원시 문자열 리터럴을 사용할 수 있습니다.
var rawText = """ Line 1, value 1 Line 2, value 2 Line 3, value 3 """; Console.WriteLine(rawText);
마지막 닫는 """ 위치에 맞게 문자열로 잘 대입됩니다.
Line 1, value 1 Line 2, value 2 Line 3, value 3
만약 문자열 안에 """가 포함되어 있을 경우, 열고 닫는 큰따옴표를 """"로 할 수 있습니다.
var rawText = """" Line 1, value 1 Line 2, value 2 Line 3, value 3 """Text""" """"; Console.WriteLine(rawText);
Line 1, value 1 Line 2, value 2 Line 3, value 3 """Text"""
또한 문자열 보간도 사용할 수 있습니다.
var num = 1; var rawText = $"""" Line 1, value {num} Line 2, value {num + 1} Line 3, value {num + 2} """Text""" """"; Console.WriteLine(rawText);
Line 1, value 1 Line 2, value 2 Line 3, value 3 """Text"""
그런데 JSON 문자열 처럼 문자열에 { 또는 }이 있을 경우 $ 대신 $$을, {value} 대신 {{value}}으로 사용할 수 있습니다.
var num = 1; var rawText = $$"""" { Line 1, value {{num}} Line 2, value {{num + 1}} Line 3, value {{num + 2}} } """Text""" """"; Console.WriteLine(rawText);
{ Line 1, value 1 Line 2, value 2 Line 3, value 3 } """Text"""
정적 메소드 그룹에 대한 캐시 대리자 (Cache delegates for static method group)
클로저가 없는 정적 메소드 그룹에 대해서 C# 11 이전에는 호출할 때마다 대리자의 새 인스턴스를 만들었습니다.
void Demo(Func  action) { } string GetString() => ""; ```csharp // C# code Demo(GetString); // -> Demo(new Func (GetString));
이제 클로저가 없으면 컴파일러는 대리자를 캐시하고 각 호출에서 재사용 합니다.
이제 매개변수의 이름 역시 nameof(parameter) 형태로 사용할 수 있게 되었습니다.
Assert(1 == 1); Assert("A" == "B"); void Assert(bool condition, [CallerArgumentExpression(nameof(condition))] string? message = default) { Console.WriteLine(nameof(condition)); Console.WriteLine(message); }
condition 1 == 1 condition "A" == "B"
시프트 연산자의 제약 완화 (Relaxing Shift Operator)
이제 시프트 연산자의 타입 완화로 다른 타입을 연산자 매개변수로 받을 수 있게 되었습니다.
// 출처 - 성태의 닷넷 이야기 C c = new C(); C d = c << 5.8f; class C { public static C operator << (C c, float o) { Console.WriteLine("shift operator called with " + o); return c; } }
제네릭 특성 (Generic attributes)
이제 특성 타입에 제네릭을 사용할 수 있게 되었습니다.
class ValueAttribute  : Attribute where TValue : struct { public TValue V { get; set; } } [Value (V = 10)] class TestClass { }
좀 더 상세한 내용은 아래의 문서를 확인하세요.
C# 11 - 메서드 매개 변수에 대한 nameof 지원
C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)
C# 11 - Span 타입에 대한 패턴 매칭 (Pattern matching on ReadOnlySpan )
C# 11 - 목록 패턴(List patterns)
C# 11 - IntPtr/UIntPtr과 nint/nuint의 통합
C# 11 - 새로운 연산자 ">>>" (Unsigned Right Shift)
C# 11 - shift 연산자 재정의에 대한 제약 완화 (Relaxing Shift Operator)
C# 11 - 사용자 정의 checked 연산자
C# 11 - UTF-8 문자열 리터럴
C# 11 - 문자열 보간 개선 2가지
C# 11 - 원시 문자열 리터럴(raw string literals)
C# 11 - ref struct에 ref 필드를 허용
C# 11 - 제네릭 타입의 특성 적용
C# 11 - 인터페이스 내에 정적 추상 메서드 정의 가능 (DIM for Static Members)
Performance: Lambda Expressions, Method Groups, and delegate caching | Gérald Barré | MEZIANTOU'S BLOG
Powered by Hashnode - a blogging community with over 2 Million members