성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[tree soap] 아차! f는 기억이 나는데, m은 ㅜㅜ 감사합니다!!! ^...
[정성태] 'm'은 decimal 타입의 숫자에 붙는 접미사입니다. ...
[정성태] https://lxr.sourceforge.io/ http...
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
글쓰기
제목
이름
암호
전자우편
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# 12 - 인라인 배열(Inline Arrays)</h1> <p> 현재(2023-09-14) <a target='tab' href='https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md'>기능 명세표</a>를 보면 C# 12의 기능이 모두 8개로 확정(및 <a target='tab' href='https://github.com/dotnet/roslyn/milestone/117'>closed 상태</a>)되었고, Visual Studio 2022 17.8.0 Preview 1.0 환경에서 "ref readonly parameters"를 제외한 7개의 문법을 모두 실습할 수 있습니다.<br /> <br /> 7개의 구문 중 4개는 알아봤고, 이번엔 남은 3개 중에서 "<a target='tab' href='https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/inline-arrays.md'>인라인 배열(Inline Arrays)</a>"에 대해 알아보겠습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 인라인 배열은, struct에 대해 InlineArray 특성을 지정하는 경우 C# 언어에서 새롭게 취급하는 배열 타입입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [System.Runtime.CompilerServices.<span style='color: blue; font-weight: bold'>InlineArray</span>(5)] public <span style='color: blue; font-weight: bold'>struct</span> Buffer { private <span style='color: blue; font-weight: bold'>int _element0</span>; // public 접근을 허용하지만 실용적이지 않음 // 필드는 단 한 개만 정의할 수 있음 } </pre> <br /> C# 컴파일러는 위와 같은 정의를 내부 필드의 타입 기준으로 InlineArray 특성에 전달된 수(예제에서는 5)만큼 연속적인 공간에 메모리가 할당된 것으로 처리합니다.<br /> <br /> 즉, 위의 예제에서는 int 타입 4바이트 * 5 = 20바이트가 연속적으로 메모리에 할당이 되는 식입니다. 이후, 사용 방법도 배열과 완전히 동일하게 취급할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > namespace ConsoleApp1; internal class Program { static void Main(string[] args) { { <span style='color: blue; font-weight: bold'>Buffer b = new Buffer(); // 새롭게 정의한 배열 타입 for (int i = 0; i < 5; i ++) { b[i] = i; // indexer 구문으로 개별 요소 접근 Console.WriteLine(b[i]); }</span> } } } [System.Runtime.CompilerServices.InlineArray(5)] public struct Buffer { private int _element0; } </pre> <br /> Inline Array 타입은 Length 속성이 없어 위의 코드에서 5개의 요소를 열거하기 위해 하드 코딩으로 5를 지정했는데, 약간 복잡하지만 다음과 같이 구할 수는 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > int len = Unsafe.SizeOf<Buffer>() / Unsafe.SizeOf<int>(); for (int i = 0; i < len; i ++) { // ... } </pre> <br /> 하지만, Span과도 연동이 되므로 이를 이용하는 것이 더 편리합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Buffer b = new Buffer(); Span<int> s = b; // Span을 경유해, for (int i = 0; i < s.Length; i ++) // s.Length를 사용해 열거 { // ... } </pre> <br /> <hr style='width: 50%' /><br /> <br /> 이렇게 만든 인라인 배열 타입을 메서드 내에서 쓰면 당연히 Stack 영역에 할당합니다. 그런 의미에서 봤을 때 기존의 stackalloc과 유사하다고도 볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // InlineArray 사용 Buffer b = new Buffer(); // 스택에 sizeof(int) * 5 크기만큼의 연속된 공간을 할당 // stackalloc 사용 int* ptr = <span style='color: blue; font-weight: bold'>stackalloc</span> int[5]; // 스택에 sizeof(int) * 5 크기만큼의 연속된 공간을 할당 </pre> <br /> 하지만 stackalloc은 unsafe 문맥을 요구하는 반면 InlineArray는 managed(safe) 환경에서 사용할 수 있습니다.<br /> <br /> 또한, <a target='tab' href='https://www.sysnet.pe.kr/2/0/11556'>C# 7.3에 추가된 fixed의 기능</a>과 유사하다고도 볼 수 있는데요,<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'>unsafe</span> struct CppStructType { public <span style='color: blue; font-weight: bold'>fixed</span> int fields[5]; // sizeof(int) * 5 크기만큼의 연속된 공간을 할당 } [System.Runtime.CompilerServices.<span style='color: blue; font-weight: bold'>InlineArray</span>(5)] // sizeof(int) * 5 크기만큼의 연속된 공간을 할당 public struct Buffer { private int _element0; } </pre> <br /> 이것 역시 마찬가지로 fixed는 unsafe 문맥을 필요로 하지만 InlineArray는 managed(safe) 환경에서 사용할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 결국, '음지'에서 천대받던 ^^ "고정 크기 (스택) 배열"을 '양지'로 끌어낸 기능이 바로 InlineArray입니다. 따라서, 이것의 도입으로 인해 1) C/C++과의 Interop을 좀 더 편하게 할 수 있게 되었고, 2) GC의 개입을 줄이기 위해 스택에 좀 더 간편하게 배열을 생성할 수 있게 되었습니다.<br /> <br /> 한 가지 유의하셔야 할 것은, 당연히 메서드 또는 다른 struct 타입 내에서 사용하는 경우 스택에 할당되기 때문에 자칫 배열 크기를 너무 크게 잡으면 Stack overflow가 발생하므로 주의해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > namespace ConsoleApp1; internal class Program { static unsafe void Main(string[] args) { Buffer b = new Buffer(); Console.WriteLine($"b: {b[0]}"); } } [System.Runtime.CompilerServices.InlineArray(<span style='color: blue; font-weight: bold'>1500000</span>)] public struct Buffer { public byte _element0; } /* 출력 결과 Stack overflow. at System.Byte.TryFormat(System.Span`1<Char>, Int32 ByRef, System.ReadOnlySpan`1<Char>, System.IFormatProvider) at System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted[[System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Byte) at ConsoleApp1.Program.Main(System.String[]) */ </pre> <br /> 반면, class 내에 정의한다면 Heap에 연속적인 배열 공간을 잡게 되므로 크기 제약이 완화됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > namespace ConsoleApp1; internal class Program { static unsafe void Main(string[] args) { MyClass m = new MyClass(); Console.WriteLine(m.Buf[4500000 - 1]); // 정상 실행 } } public class MyClass { public Buffer Buf; } [System.Runtime.CompilerServices.InlineArray(<span style='color: blue; font-weight: bold'>4500000</span>)] public struct Buffer { private int _element0; } </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
5127
(왼쪽의 숫자를 입력해야 합니다.)