성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
[공진영] 안녕하세요 좋은글 감사합니다. 현재 제가 wpf로 관제 모...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# 10 - (14) 구조체 타입에 기본 생성자 정의 가능</h1> <p> 그동안, 구조체에 기본 생성자를 정의할 수 있게 해달라는 요구 사항이 있었지만 지금까지 미뤄오던 마이크로소프트가 드디어 ^^ C# 10에서 이 기능을 제공하게 되었습니다. 아마도 이번 역시 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12790'>record struct</a>가 나오면서 기본 생성자가 없는 record 정의가 기존의 record class에 비해 제약이 많아 더 미룰 수 없어 지원하게 된 것이 아닌가... 생각됩니다.<br /> <br /> 그나저나, 아래에서 나열한 것들을 보면... 단지 기본 생성자 하나에 이렇게나 많이 주변 상황이 엮이는 것을 보면... 이 기능을 지원하지 않았던 마이크로소프트의 심정을 조금은 이해할 수 있을 것 같습니다. ^^;<br /> <br /> <hr style='width: 50%' /><br /> <br /> 제목에서처럼 이제 구조체에 기본 생성자를 사용할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public struct S { public int i; <span style='color: blue; font-weight: bold'>public S() { i = 10; }</span> } // Get the default value of a type at runtime (Activator.CreateInstance vs untimeHelpers.GetUninitializedObject) // <a target='tab' href='https://www.meziantou.net/get-the-default-value-of-a-type-at-runtime.htm'>https://www.meziantou.net/get-the-default-value-of-a-type-at-runtime.htm</a> </pre> <br /> 다소 헷갈릴 수 있지만 아래의 경우는 (기본 생성자가 아닌) 기본값이 설정된 인자를 가진 생성자이기 때문에 (구조체의 기본 생성자를 호출하기 위한) new() 코드에서는 바인딩이 되지 않습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct S1 { public <span style='color: blue; font-weight: bold'>S1(string s = "test")</span> { Console.WriteLine(s); } } struct S2 { public <span style='color: blue; font-weight: bold'>S2(params object[] args)</span> { Console.WriteLine(args.Length); } } public class Test { public void Create() { { S1 instance1 = <span style='color: blue; font-weight: bold'>new S1()</span>; // S1 생성자 호출이 되지 않음 S2 instance2 = <span style='color: blue; font-weight: bold'>new S2()</span>; // S2 생성자 호출이 되지 않음 } { S1 instance1 = new <span style='color: blue; font-weight: bold'>S1(s: "test5")</span>; // 명시적으로 인자를 가진 생성자 호출 S2 instance2 = new <span style='color: blue; font-weight: bold'>S2(args: "test5")</span>; // 명시적으로 인자를 가진 생성자 호출 } } } </pre> <br /> 아울러 (대부분의 경우겠지만) 구조체가 필드를 가진다면 기본 생성자를 명시적으로 사용하는 경우 반드시 모든 필드가 초기화되어야 합니다. 가령 다음과 같은 경우는 모두 컴파일 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct Init0 { <span style='color: blue; font-weight: bold'>public int intField;</span> public string textField; // intField의 초기화 누락: 컴파일 오류 - error CS0171: Field 'Init0.intField' must be fully assigned before control is returned to the caller public Init0() { textField = "None"; } } struct Init1 { public int intField; <span style='color: blue; font-weight: bold'>public string textField;</span> public float floatField = 0.5f; // textField 초기화 누락: error CS0171: Field 'Init1.textField' must be fully assigned before control is returned to the caller public Init1() { intField = 5; } } struct Init2 { <span style='color: blue; font-weight: bold'>public int intField;</span> // 일단 생성자를 정의했다면 모든 필드를 초기화해야 함: error CS0171: Field 'Init2.intField' must be fully assigned before control is returned to the caller public Init2() { } } </pre> <br /> 즉, 필드 선언에 초기화를 한 것과 생성자의 초기화를 합쳐 어쨌든 모든 필드가 초기화를 마쳐야만 합니다. 따라서 다음의 생성자 사용은 유효합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct Init3 { public int intField; public float <span style='color: blue; font-weight: bold'>floatField = 0.5f</span>; // 필드 초기화와 생성자 초기화를 통해 모든 멤버 초기화 완료 public Init3() { <span style='color: blue; font-weight: bold'>intField = 5</span>; } } struct Init4 { public int <span style='color: blue; font-weight: bold'>intField = 5</span>; public float <span style='color: blue; font-weight: bold'>floatField = 0.5f</span>; // 모든 필드 초기화로 생성자에서는 초기화 코드 필요 없음 public Init4() { } } struct Init5 { public int intField; public float floatField; // 생성자에서 모든 필드 초기화 public Init5() { <span style='color: blue; font-weight: bold'>intField = 5;</span> <span style='color: blue; font-weight: bold'>floatField = 0.5f;</span> } } </pre> <br /> 필드 초기화의 경우 결국 생성자의 코드로 병합이 됩니다. 생성자 내의 초기화 순서상으로 보면 필드 초기화 코드가 먼저 오고, 이후 생성자에 명시한 코드가 옵니다. 따라서, 위의 Init3, Init4 구조체는 결국 다음과 같이 생성자의 코드로 병합이 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct Init3 { public int intField; public float floatField; <span style='color: blue; font-weight: bold'>// = 0.5f;</span> public Init3() { <span style='color: blue; font-weight: bold'>floatField = 0.5f;</span> // 필드 초기화 먼저! intField = 5; } } struct Init4 { public int intField; <span style='color: blue; font-weight: bold'>// = 5;</span> public float floatField; <span style='color: blue; font-weight: bold'>// = 0.5f;</span> public Init4() { // 소스 코드에 명시한 순서로 초기화 <span style='color: blue; font-weight: bold'>intField = 5; float floatField = 0.5f;</span> } } </pre> <br /> 따라서 필드 초기화를 한 경우 생성자에서도 중복돼 있다면 생성자의 코드가 최종 값이 됩니다. 또한 필드 초기화는 인자를 갖는 생성자가 있다면 그곳에도 함께 병합이 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct Init6 { public int intField = 5; public float floatField; public Init6() { <span style='color: blue; font-weight: bold'>// 이곳에 intField = 5 코드가 삽입됨</span> floatField = 5.0f; } public Init6(float value) { <span style='color: blue; font-weight: bold'>// 이곳에도 intField = 5 코드가 삽입됨</span> floatField = value; } } </pre> <br /> <hr style='width: 50%' /><br /> <br /> 유의할 것은, 기본 생성자를 정의했다고 해서 new를 사용하지 않은 경우의 구조체 인스턴스가 선언되었을 때 자동으로 생성자가 불리지는 않습니다<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static class Program { static void WriteValue(Person instance) { Console.WriteLine(instance.Age); Console.WriteLine(instance.Name); } public static void Main() { { <span style='color: blue; font-weight: bold'>Person instance; // 기본 생성자가 호출된 것은 아니므로!</span> // 컴파일 에러 - error CS0165: Use of unassigned local variable 'instance' WriteValue(instance); } { Person instance; // 생성자가 호출되지는 않았지만, // 모든 필드를 초기화했으므로, instance.Age = 35; instance.Name = "Anders"; // 정상적으로 호출 가능 WriteValue(instance); } { Person instance = new Person(); // 기본 생성자가 호출돼 모든 필드가 초기화되었으므로! WriteValue(instance); // 컴파일 가능 } } } public struct Person { public int Age; public string Name; public Person() { <span style='color: blue; font-weight: bold'>Age = 1; Name = "Doe";</span> } } </pre> <br /> 위에서 보는 것처럼, C# 컴파일러는 해당 구조체의 멤버가 사용되기 전 초기화가 안 되었음을 알고 있으므로 그에 따른 컴파일 오류를 냅니다. 하지만, 이런 필드 초기화 판단을 할 수 없는 경우가 있는데, 다음과 같이 인자가 있는 생성자를 가진 구조체에 대해 new를 하는 경우입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct S { public int i = 5; public <span style='color: blue; font-weight: bold'>S(int i)</span> { this.i = i; } } public class Test { static T CreateNew<T>() where T : new() => <span style='color: blue; font-weight: bold'>new T();</span> // 기본 생성자가 없으면 무시, 있으면 호출 public void Create() { // 클래스의 경우 기본 생성자 없이 인자만 가진 생성자가 있으면 컴파일 오류가 발생하지만, // 구조체의 경우에는 가능 { S instance = <span style='color: blue; font-weight: bold'>new S();</span> // 필드 i가 초기화되지 않았지만 컴파일 성공 // <a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/parameterless-struct-constructors#new'>공식 문서</a>에서는 경고가 발생한다고 하지만, 현재 테스트로는 경고 없음 Console.WriteLine(instance.i); // 출력 결과: 0 } { S instance = <span style='color: blue; font-weight: bold'>CreateNew<S>();</span> // 필드 i가 초기화되지 않았지만 컴파일 성공 Console.WriteLine(instance.i); // 출력 결과: 0 } } } </pre> <br /> new의 또 다른 사례로, 메서드의 기본 값 구문에 사용된다면 기본 생성자를 가진 인스턴스는 컴파일 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public struct WithCtor { public WithCtor() { } } public struct WithoutCtor { } public class Test { // 기본 생성자를 가진 타입의 경우 // 컴파일 오류 - error CS1736: Default parameter value for 'instance' must be a compile-time constant public void Default(<span style='color: blue; font-weight: bold'>WithCtor instance = new()</span>) { } // 기본 생성자가 없는 타입의 경우 - 컴파일 허용 public void Default(<span style='color: blue; font-weight: bold'>WithoutCtor instance = new()</span>) { } } </pre> <br /> 또한, 구조체 내에 구조체를 포함하는 경우에도 생성자가 호출되지 않고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct S0 { public S0() { } // 생성자를 가진 S0 타입 } struct S1 { S0 F; // S0 생성자 호출 없음 } struct S<T> where T : struct { T F; // 형식 인자 T로 생성자를 가진 구조체가 와도 생성자 호출 없음 } </pre> <br /> default 식도 생성자를 배려하지 않으며,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > _ = default(S0); // S0 타입이 생성자가 있어도 호출되지는 않음 </pre> <br /> 배열에서도 생성자 호출은 없습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct S { public S() { } } var a = new S[10]; // 10개의 구조체 모두 생성자 호출은 없음 </pre> <br /> <hr style='width: 50%' /><br /> <br /> 클래스와는 달리 구조체의 경우 public 이외의 접근자를 가진 기본 생성자를 정의할 수 없습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct S1 { <span style='color: blue; font-weight: bold'>public</span> S1() { } } // 가능 // 컴파일 오류 - error CS8958: The parameterless struct constructor must be 'public'. struct S2 { <span style='color: blue; font-weight: bold'>internal</span> S2() { } } </pre> <br /> 따라서 Factory 패턴이나, Singleton 패턴을 구현하기에는 적당하지 않습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> this를 이용해 생성자 간에 연결은 가능하지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public struct Vector { public float X; public float Y; <span style='color: blue; font-weight: bold'>public Vector() : this(0.0f, 0.0f)</span> { } public Vector(float x, float y) { this.X = x; this.Y = y; } } </pre> <br /> base 호출은 할 수 없습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public struct Point { public int X; public int Y; // 컴파일 오류 - error CS0522: 'Point': structs cannot call base class constructors <span style='color: blue; font-weight: bold'>public Point() : base()</span> { X = 0; Y = 0; } } </pre> <br /> 사실 모든 struct는 sealed 유형이므로 상속이 불가능해 base 생성자를 호출하는 것이 (굳이 막을 필요도 없었겠지만) 의미가 없긴 합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 당연히 위의 모든 변화는 <a target='tab' href='https://www.sysnet.pe.kr/2/0/12790'>record struct</a>에도 반영이 되고, 원칙은 위에서 설명한 것과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > record struct R1 { int F = 42; // 기본 생성자에서 초기화 } record struct R2<span style='color: blue; font-weight: bold'>(int F)</span> { int F = F; // (기본 생성자가 아닌) int F를 인자로 받는 생성자에서 초기화 } record struct R3<span style='color: blue; font-weight: bold'>(int F)</span> { <span style='color: blue; font-weight: bold'>public R3() : this(0)</span> { } // 반드시 (int F) 생성자 호출을 해 필드 초기화 } </pre> <br /> 위의 코드는 record struct가 가진 몇몇 특이함을 보여줍니다. 가령 R3 구조체의 경우, "record struct R3<span style='color: blue; font-weight: bold'>(int F)</span>"로 인해 추가되는 생성자를 this로 호출하지 않고, 다음과 같이 초기화 코드를 포함하는 식으로 바꿔도 오류가 발생합니다. <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > record struct R3<span style='color: blue; font-weight: bold'>(int F)</span> // 이렇게 생성자가 정의되는 경우, { // 필드 초기화를 했어도 컴파일 오류, 반드시 this로 연계해 필드 초기화 // error CS8862: A constructor declared in a record with parameter list must have 'this' constructor initializer. public R3() { this.F = 0; } } </pre> <br /> 또한 R2의 경우 굳이 필드 초기화를 할 필요가 없어 다음의 코드와 동일합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > record struct R2(int F); </pre> <br /> 즉, R1과 R2는 다음과 같은 식으로 생성자 코드에 병합됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > record struct R1 { int F; // = 42; public R1() // 인자 없는 생성자에 병합 { F = 42; } } record struct R2<span style='color: blue; font-weight: bold'>(int F)</span> { int F; // = F; <span style='color: blue; font-weight: bold'>public R2(int F)</span> // 기존의 생성자 코드에 병합 { this.F = F; } } </pre> <br /> 마지막으로 현실적인 사용 사례로 봤을 때, C# 10에서 struct의 기본 생성자를 허용하게 된 것은, 결국 다음과 같이 record class/struct를 동일한 방식의 초기화 코드로 다룰 수 있도록 만들고 싶었기 때문일 듯합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>record struct</span> Student() { public string Name { get; init; } = ""; public object Id { get; init; } = DateTime.Now; public int Age { get; init; } = 0; } <span style='color: blue; font-weight: bold'>record class</span> Teacher() { public string Name { get; init; } = ""; public object Id { get; init; } = DateTime.Now; public int Age { get; init; } = 0; } </pre> <br /> <hr style='width: 50%' /><br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# 10 - (1) 구조체를 생성하는 record struct (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/record-structs'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4334'>Static Abstract Members In Interfaces C# 10 Preview)</a> ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12790'>https://www.sysnet.pe.kr/2/0/12790</a> C# 10 - (2) 전역 네임스페이스 선언 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/globalusingdirective'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/3428'>Global Using Directive</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12792'>https://www.sysnet.pe.kr/2/0/12792</a> C# 10 - (3) 개선된 변수 초기화 판정 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-definite-assignment'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4465'>Improved Definite Assignment</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12793'>https://www.sysnet.pe.kr/2/0/12793</a> C# 10 - (4) 상수 문자열에 포맷 식 사용 가능 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-interpolated-strings'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/2951'>Constant Interpolated Strings</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12796'>https://www.sysnet.pe.kr/2/0/12796</a> C# 10 - (5) 속성 패턴의 개선 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/extended-property-patterns'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4394'>Extended property patterns</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12799'>https://www.sysnet.pe.kr/2/0/12799</a> C# 10 - (6) record class 타입의 ToString 메서드를 sealed 처리 허용 (공식 문서, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4174'>Sealed record ToString</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12801'>https://www.sysnet.pe.kr/2/0/12801</a> C# 10 - (7) Source Generator V2 APIs (<a target='tab' href='https://github.com/dotnet/roslyn/issues/51257'>Source Generator V2 APIs</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12804'>https://www.sysnet.pe.kr/2/0/12804</a> C# 10 - (8) 분해 구문에서 기존 변수의 재사용 가능 (공식 문서, <a target='tab' href='https://github.com/dotnet/csharplang/issues/125'>Mix declarations and variables in deconstruction</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12805'>https://www.sysnet.pe.kr/2/0/12805</a> C# 10 - (9) 비동기 메서드가 사용할 AsyncMethodBuilder 선택 가능 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/async-method-builders'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/1407'>Async method builder override</a>); ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12807'>https://www.sysnet.pe.kr/2/0/12807</a> C# 10 - (10) 개선된 #line 지시자 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/enhanced-line-directives'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4747'>Enhanced #line directive</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12812'>https://www.sysnet.pe.kr/2/0/12812</a> C# 10 - (11) Lambda 개선 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/lambda-improvements'>공식 문서 1</a>, <a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/lambda-attributes'>공식 문서 2</a>, <a target='tab' href='https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/lambda-improvements.md'>Lambda improvements</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12813'>https://www.sysnet.pe.kr/2/0/12813</a> C# 10 - (12) 문자열 보간 성능 개선 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/improved-interpolated-strings'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/4487'>Interpolated string improvements</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12826'>https://www.sysnet.pe.kr/2/0/12826</a> C# 10 - (13) 단일 파일 내에 적용되는 namespace 선언 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/file-scoped-namespaces'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/137'>File-scoped namespace</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12828'>https://www.sysnet.pe.kr/2/0/12828</a> C# 10 - (14) 구조체 타입에 기본 생성자 정의 가능 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/parameterless-struct-constructors'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/99'>Parameterless struct constructors</a>) ; https://www.sysnet.pe.kr/2/0/12829 C# 10 - (15) CallerArgumentExpression 특성 추가 (<a target='tab' href='https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression'>공식 문서</a>, <a target='tab' href='https://github.com/dotnet/csharplang/issues/287'>Caller expression attribute</a>) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12835'>https://www.sysnet.pe.kr/2/0/12835</a> Language Feature Status ; <a target='tab' href='https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md'>https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7720
(왼쪽의 숫자를 입력해야 합니다.)