성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 그냥 RSS Reader 기능과 약간의 UI 편의성 때문에 사용...
[이종효] 오래된 소프트웨어는 보안 위협이 되기도 합니다. 혹시 어떤 기능...
[정성태] @Keystroke IEEE의 문서를 소개해 주시다니... +_...
[손민수 (Keystroke)] 괜히 듀얼채널 구성할 때 한번에 같은 제품 사라고 하는 것이 아...
[정성태] 전각(Full-width)/반각(Half-width) 기능을 토...
[정성태] Vector에 대한 내용은 없습니다. Vector가 닷넷 BCL...
[orion] 글 읽고 찾아보니 디자인 타임에는 InitializeCompon...
[orion] 연휴 전에 재현 프로젝트 올리자 생각해 놓고 여의치 않아서 못 ...
[정성태] 아래의 글에 정리했으니 참고하세요. C# - Typed D...
[정성태] 간단한 재현 프로젝트라도 있을까요? 저런 식으로 설명만 해...
글쓰기
제목
이름
암호
전자우편
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# 7.2 - 스택에만 생성할 수 있는 값 타입 지원 - "ref struct"</h1> <p> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# 7.2 (1) - readonly 구조체 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11524'>http://www.sysnet.pe.kr/2/0/11524</a> C# 7.2 (2) - 메서드의 매개 변수에 in 변경자 추가 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11525'>http://www.sysnet.pe.kr/2/0/11525</a> C# 7.2 (3) - 메서드의 반환값 및 로컬 변수에 ref readonly 기능 추가 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11526'>http://www.sysnet.pe.kr/2/0/11526</a> C# 7.2 (4) - 3항 연산자에 ref 지원(conditional ref operator) ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11528'>http://www.sysnet.pe.kr/2/0/11528</a> C# 7.2 (5) - 스택에만 생성할 수 있는 값 타입 지원 - "ref struct" ; http://www.sysnet.pe.kr/2/0/11530 C# 7.2 (6) - Span<T> ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11534'>http://www.sysnet.pe.kr/2/0/11534</a> C# 7.2 (7) - private protected 접근자 추가 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11543'>http://www.sysnet.pe.kr/2/0/11543</a> C# 7.2 (8) - 숫자 리터럴의 선행 밑줄과 뒤에 오지 않는 명명된 인수 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11544'>http://www.sysnet.pe.kr/2/0/11544</a> 기타 - Microsoft Build 2018 - The future of C# 동영상 내용 정리 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11536'>http://www.sysnet.pe.kr/2/0/11536</a> </pre> <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;' > 닷넷의 관리 포인터(Managed Pointer)와 System.TypedReference ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11529'>http://www.sysnet.pe.kr/2/0/11529</a> </pre> <br /> 설명한 System.TypedReference는 내부에 "관리 포인터"를 가지고 있으며, 그 특성으로 인해 관리 힙에 놓일 수 없는 타입이라고 했습니다. 이렇게 "스택에만 생성할 수 있는 타입"을 정의할 수 있는 C# 문법이 바로 7.2부터 제공되는 "ref struct"입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# 7 Series, Part 9: ref structs ; <a target='tab' href='https://blogs.msdn.microsoft.com/mazhou/2018/03/02/c-7-series-part-9-ref-structs/'>https://blogs.msdn.microsoft.com/mazhou/2018/03/02/c-7-series-part-9-ref-structs/</a> ref struct ; <a target='tab' href='https://docs.microsoft.com/ko-kr/dotnet/csharp/reference-semantics-with-value-types'>https://docs.microsoft.com/ko-kr/dotnet/csharp/reference-semantics-with-value-types</a> Compile time enforcement of safety for ref-like types [7.2 Proposal] ; <a target='tab' href='https://www.infoq.com/news/2017/06/CSharp-7.2'>https://www.infoq.com/news/2017/06/CSharp-7.2</a> Compile time enforcement of safety for ref-like types ; <a target='tab' href='https://github.com/VSadov/csharplang/blob/ef68acb505ad1a3310de133ef7af65c2c24da520/proposals/span-safety.md'>https://github.com/VSadov/csharplang/blob/ef68acb505ad1a3310de133ef7af65c2c24da520/proposals/span-safety.md</a> </pre> <br /> (위의 링크에서 제목 중에 "ref-like types"라고 불리는 것이 "ref struct"입니다.)<br /> <br /> 사용 방법은 단순히 "ref 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'>ref struct</span> Vector { public int X; public int Y; public int Z; public void Output() { Console.WriteLine($"{X},{Y},{Z}"); } } </pre> <br /> "스택에만 생성할 수 있는 타입"이므로 로컬 변수와 매개 변수에 사용할 수 있고, TypedReference와 달리 내부에 "관리 포인터"를 가지고 있지는 않으므로 변수의 반환에서도 (struct의 값 복사 특성으로 인해) "로컬 변수"인 경우 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; <span style='color: blue; font-weight: bold'>ref struct</span> Vector { public int X; public int Y; public int Z; } class Program { // 컴파일 오류: CS8345 Field or auto-implemented property cannot be of type 'Vector' unless it is an instance member of a ref struct. // Vector vector; // 타입의 멤버는 불가능 static void Main(string[] args) { // 로컬 변수로 스택에 생성되므로 OK! Vector v = new Vector { X = 0, Y = 0, Z = 0 }; v.X = 50; Console.WriteLine(v.X); PassVector(v); PassVectorIn(in v); } private static void PassVectorIn(in Vector v) // in 매개 변수로 가능 { } private static void PassVector(Vector v) // 매개 변수로 가능 (스택에 복사되어 전달되므로.) { } private static Vector GetVector() { Vector v = new Vector { X = 1, Y = 2, Z = 3 }; return v; // 로컬 변수의 반환으로도 가능 } } </pre> <br /> 스택에만 생성할 수 있다는 제약으로 인해 당연히 다른 "ref 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'>ref struct</span> Matrix3x3 { public <span style='color: blue; font-weight: bold'>Vector</span> v1; public <span style='color: blue; font-weight: bold'>Vector</span> v2; public <span style='color: blue; font-weight: bold'>Vector</span> v3; } </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;' > static void Main(string[] args) { Vector v = new Vector { X = 0, Y = 0, Z = 0 }; <span style='color: blue; font-weight: bold'>v.Output();</span> } ref struct Vector { public int X; public int Y; public int Z; <span style='color: blue; font-weight: bold'>public void Output() { Console.WriteLine($"{X},{Y},{Z}"); }</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;' > Vector v = new Vector { X = 0, Y = 0, Z = 0 }; // 컴파일 오류: CS0029 Cannot implicitly convert type 'ret_struct.Vector' to 'object' v.GetType(); // 컴파일 오류: CS0029 Cannot implicitly convert type 'reflike.Vector' to 'System.ValueType' v.ToString(); // 컴파일 오류: CS0029 Cannot implicitly convert type 'reflike.Vector' to 'System.ValueType' v.Equals(null); // 컴파일 오류: CS0029 Cannot implicitly convert type 'reflike.Vector' to 'System.ValueType' v.GetHashCode(); </pre> <br /> 물론, 위의 메서드 중 ToString, Equals, GetHashCode는 ref struct 타입 내에서 재정의(override)하면 사용 가능합니다.<br /> <br /> 개인적으로 처음 ref struct를 봤을 때 System.TypedReference와 같은 타입을 이제 C#으로도 정의할 수 있게 길을 열어주는 것이 아닌가 생각했었습니다. 하지만, 여전히 ref struct 타입도 관리 포인터를 내부에 정의할 수 없는 제약을 가지고 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ref struct IncludeManagedPointer { // 컴파일 에러 - CS0501 'IncludeManagedPointer.Age()' must declare a body because it is not marked abstract, extern, or partial ref_struct public <span style='color: blue; font-weight: bold'>ref int</span> Age; } </pre> <br /> 따라서, ref struct는 스택에만 할당할 수 있는 특별한 타입 정의에 불과합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> ref struct 구조체 역시 readonly 구조체를 지원합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# 7.2 - readonly 구조체 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11524'>http://www.sysnet.pe.kr/2/0/11524</a> </pre> <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'>readonly ref struct</span> Vector { public readonly int X; public readonly int Y; public readonly int Z; public Vector(int x, int y, int z) { X = x; Y = y; Z = z; } public void Output() { Console.WriteLine($"{X},{Y},{Z}"); } } </pre> <br /> 그건 그렇다 치고... 그나저나 이런 타입을 도대체 어디다 써먹어야 할까요? ^^ 사실, 일반 개발자들에게는 거의 잊고 지내도 좋을 문법입니다. 아마도 이것은 마이크로소프트가 Span<T>를 위해 도입한 문법일 것이기 때문입니다.<br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1259&boardid=331301885'>첨부 파일은 이 글의 예제를 포함</a>합니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1921
(왼쪽의 숫자를 입력해야 합니다.)