내용 보기
작성자
관리자 (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