내용 보기
작성자
관리자 (IP : 106.247.248.10)
날짜
2022-12-21 09:30
제목
[C#] [스크랩] 값 형식의 readonly 인스턴스에 대한 메서드 호출 시 defensive copy 발생
readonly 예약어가 기본형 타입에 적용되었을 때에는 명확하게 읽기 전용이 됩니다. 그런데, 클래스나 구조체 타입의 인스턴스에 대해서는 다소 의미가 달라집니다. using System; class Program { readonly StructPerson sarah = new StructPerson() { Name = "Kerrigan", Age = 27 }; readonly ClassPerson james = new ClassPerson() { Name = "Raynor", Age = 30 }; static void Main(string[] args) { Program pg = new Program(); pg.Test(); } private void Test() { // sarah.Age = 32; // 컴파일 오류: CS1648 Members of readonly field 'Program.sarah' cannot be modified (except in a constructor or a variable initializer) james.Age = 32; // 참조 형식의 경우 readonly 인스턴스의 멤버는 대입 가능 Console.WriteLine("sarah age: " + sarah.Age); Console.WriteLine("james age: " + james.Age); // 출력 결과: james age: 32 } } struct StructPerson { public int Age; public string Name; } class ClassPerson { public int Age; public string Name; }
private void Test() { sarah.IncAge(); james.IncAge(); Console.WriteLine("sarah age: " + sarah.Age); // 출력 결과: sarah age: 27 Console.WriteLine("james age: " + james.Age); // 출력 결과: james age: 31 } struct StructPerson { public int Age; public string Name; public void IncAge() { Age++; } } class ClassPerson { public int Age; public string Name; public void IncAge() { Age++; } }
IL_0001: ldarg.0 // this IL_0002: ldfld valuetype readonly_value_ref.StructPerson readonly_value_ref.Program::sarah IL_0007: stloc.0 // V_0 IL_0008: ldloca.s V_0 IL_000a: call instance void readonly_value_ref.StructPerson::IncAge() IL_000f: nop IL_0010: ldarg.0 // this IL_0011: ldfld class readonly_value_ref.ClassPerson readonly_value_ref.Program::james IL_0016: callvirt instance void readonly_value_ref.ClassPerson::IncAge() IL_001b: nop
StructPerson temp = sarah; temp.IncAge(); james.IncAge();
The 'in'-modifier and the readonly structs in C# ; https://blogs.msdn.microsoft.com/seteplia/2018/03/07/the-in-modifier-and-the-readonly-structs-in-c/
internal class ReadOnlyEnumerator { private readonly List<int>.Enumerator _enumerator; public ReadOnlyEnumerator(List<int> list) { _enumerator = list.GetEnumerator(); } public void PrintTheFirstElement() { _enumerator.MoveNext(); Console.WriteLine(_enumerator.Current); // 출력 결과: 0 } } var roe = new ReadOnlyEnumerator(new List<int>{1,2}); roe.PrintTheFirstElement();
public void PrintTheFirstElement_Decompiled() { // 첫 번째 Defensive copy 발생 var localEnumerator = _enumerator; localEnumerator.MoveNext(); // 두 번째 Defensive copy 발생 localEnumerator = _enumerator; Console.WriteLine(localEnumerator.Current); }
|
출처1
https://www.sysnet.pe.kr/2/0/11523
출처2