Tuple 은 절차적이지 않습니다.

문제: 다음 달을 계산하시오

int year = 2024;
int month = 11;

절차적 접근법

// year first
year += month / 12;
month = month % 12 + 1;
Console.WriteLine($"year first: {year} / {month}");
// month first
month = month % 12 + 1;
year += month / 12;
Console.WriteLine($"month first: {year} / {month}");

결과

year first: 2024 / 12
month first: 2025 / 12

year 와 month 의 계산 순서가 중요함 => 에러 유발 요소

Tuple 사용

// year left
(year, month) = (year + month / 12, month % 12 + 1);
Console.WriteLine($"year left: {year} / {month}");
// month left
(month, year) = (month % 12 + 1, year + month / 12);
Console.WriteLine($"month left: {year} / {month}");

결과

year left: 2024 / 12
month left: 2024 / 12

year 와 month 의 계산 순서가 중요하지 않음. => 안전

4 Likes

전에 튜플 관련해서 IL 까보니까
보통은 임시 변수 하나를 생성해서 계산을 하고
후에 대입 하는 식으로 하더라고요.

linqpad의 IL+Native로 구경해보면…

int year = 2024;
int month = 11;
// year left
(year, month) = (year + month / 12, month % 12 + 1);
Console.WriteLine($"year left: {year} / {month}");

이게

 int year = 2024;
 int month = 11;
 int num = year + month / 12;
 month = month % 12 + 1;
 year = num;
 DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler (14, 2);
   defaultInterpolatedStringHandler.AppendLiteral ("year left: ");
   defaultInterpolatedStringHandler.AppendFormatted (year);
   defaultInterpolatedStringHandler.AppendLiteral (" / ");
   defaultInterpolatedStringHandler.AppendFormatted (month);
   Console.WriteLine (defaultInterpolatedStringHandler.ToStringAndClear ());
IL_0001	ldc.i4	E8 07 00 00  // 2024
IL_0006	stloc.0	   // year
IL_0007	ldc.i4.s	0B  // 11
IL_0009	stloc.1	   // month
IL_000A	ldloc.0	   // year
IL_000B	ldloc.1	   // month
IL_000C	ldc.i4.s	0C  // 12
IL_000E	div	
IL_000F	add	
IL_0010	ldloc.1	   // month
IL_0011	ldc.i4.s	0C  // 12
IL_0013	rem	
IL_0014	ldc.i4.1	
IL_0015	add	
IL_0016	stloc.1	   // month
IL_0017	stloc.0	   // year
IL_0018	ldloca.s	02 
IL_001A	ldc.i4.s	0E  // 14
IL_001C	ldc.i4.2	
IL_001D	call	DefaultInterpolatedStringHandler..ctor
IL_0022	ldloca.s	02 
IL_0024	ldstr	"year left: "
IL_0029	call	DefaultInterpolatedStringHandler.AppendLiteral (String)
IL_002E	nop	
IL_002F	ldloca.s	02 
IL_0031	ldloc.0	   // year
IL_0032	call	DefaultInterpolatedStringHandler.AppendFormatted<Int32> (Int32)
IL_0037	nop	
IL_0038	ldloca.s	02 
IL_003A	ldstr	" / "
IL_003F	call	DefaultInterpolatedStringHandler.AppendLiteral (String)
IL_0044	nop	
IL_0045	ldloca.s	02 
IL_0047	ldloc.1	   // month
IL_0048	call	DefaultInterpolatedStringHandler.AppendFormatted<Int32> (Int32)
IL_004D	nop	
IL_004E	ldloca.s	02 
IL_0050	call	DefaultInterpolatedStringHandler.ToStringAndClear ()
IL_0055	call	Console.WriteLine (String)

이렇게 변환된다고 하네요!

3 Likes

변수 재할당은 항상 코드를 읽기 어렵게 하죠

1 Like
(x, y) = (y, x);

이것만 보아도 뭐… 절차적이지 않은건 당연한 것 같아요

2 Likes