성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
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 - readonly 구조체</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 구조체 ; http://www.sysnet.pe.kr/2/0/11524 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" ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11530'>http://www.sysnet.pe.kr/2/0/11530</a> 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 /> 지난 글에서 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# - 값 형식의 readonly 인스턴스에 대한 메서드 호출 시 defensive copy 발생 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11523'>http://www.sysnet.pe.kr/2/0/11523</a> </pre> <br /> 값 타입(struct) readonly 인스턴스의 경우 "defensive copy"와 같은 C# 컴파일러의 노력을 통해 값을 변경할 수 없게 만들었다는 것을 설명했는데요. 반면, 지난번 예제에서 봤듯이 "defensive copy"는 의도치 않은 부작용을 낳습니다. 그 이외에도 "defensive copy"는 숨겨진 코드로 인한 값 복사로 메서드 및 공용 속성을 접근할 때 성능 저하가 발생하는 문제도 있습니다.<br /> <br /> C# 7.2부터 이런 문제를 아예 미연에 방지할 수 있도록 readonly 구조체(struct)를 정의할 수 있게 합니다. 예를 들기 위해 지난번 예제 코드에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class Program { readonly StructPerson sarah = new StructPerson() { Name = "Kerrigan", Age = 27 }; static void Main(string[] args) { Program pg = new Program(); pg.Test(); } private void Test() { sarah.IncAge(); } } struct StructPerson { public int Age; public string Name; public void IncAge() { Age++; } } </pre> <br /> StructPerson 구조체에 readonly를 부여해 보겠습니다.<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'>readonly</span> struct StructPerson { public int Age; // 컴파일 에러: CS8340 Instance fields of readonly structs must be readonly. public string Name; // 컴파일 에러: CS8340 Instance fields of readonly structs must be readonly. public void IncAge() { Age++; } } </pre> <br /> 보는 바와 같이 struct에 readonly를 부여하면 내부의 모든 필드에 readonly를 부여해야 한다고 강제력을 갖게 되므로 다음과 같이 고쳐야 합니다.<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'>readonly</span> struct StructPerson { public <span style='color: blue; font-weight: bold'>readonly</span> int Age; public <span style='color: blue; font-weight: bold'>readonly</span> string Name; public void IncAge() { Age++; } } </pre> <br /> 이 때문에, 해당 필드들은 반드시 생성자 내에서만 초기화될 수 있고, IncAge와 같은 메서드 내에서는 자연스럽게 값을 변경할 수 없게 됩니다. 따라서 코드는 다시 다음과 같이 바뀌어야 합니다.<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'>readonly</span> struct StructPerson { public readonly int Age; public readonly string Name; <span style='color: blue; font-weight: bold'>public StructPerson(string name, int age) { Name = name; Age = age; }</span> public StructPerson IncAge() { <span style='color: blue; font-weight: bold'>return new StructPerson(this.Name, this.Age + 1);</span> } } </pre> <br /> 오호... 위의 코드를 보니 뭔가 연상되지 않나요? 그렇습니다. readonly 구조체는 부작용 없는 불변(immutable) 객체를 만들기 위한 강제성을 부여할 수 있는 방법입니다. 자, 그럼 <a target='tab' href='http://www.sysnet.pe.kr/2/0/11523'>지난번 코드</a>에서 readonly 필드인 경우 "defensive copy"가 발생했던 호출 측의 코드를 보겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class Program { <span style='color: blue; font-weight: bold'>readonly StructPerson sarah = new StructPerson("Kerrigan", 27);</span> static void Main(string[] args) { Program pg = new Program(); pg.Test(); } private void Test() { <span style='color: blue; font-weight: bold'>sarah.IncAge();</span> /* 일반 구조체의 경우 IncAge 메서드 호출은 다음과 같은 코드로 바뀌지만, StructPerson temp = sarah; temp.IncAge(); */ } } </pre> <br /> 이제 C# 컴파일러는 Test 메서드 내에서 호출한 IncAge에 대해 더 이상 "defensive copy" 코드를 생성하지 않습니다. 왜냐하면 해당 구조체의 모든 메서드 및 공용 속성은 내부 상태 값을 변경할 수 없다는 것이 보장되었기 때문에 굳이 상태 보존을 위한 값 복사 코드를 넣을 필요가 없는 것입니다.<br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1254&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> readonly 구조체를 설명하기 위해 지난 글에서 "defensive copy"까지 설명했어야 하는데요. 정리해 보면, 굳이 그런 어려운 용어를 기억할 필요 없이 다음과 같이만 알아두면 됩니다.<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부터, 불변(immutable) 객체를 만들 때는 readonly 구조체를 사용한다! 또한 대개의 경우 struct는 불변 객체로 만들지 않을 이유가 없으므로 가능한 struct는 모두 readonly 구조체로 만든다! </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2115
(왼쪽의 숫자를 입력해야 합니다.)