C# 메서드 오버로드로 최적화되는지 확인하기 IL
- 출처 : https://www.dotnetperls.com/overload [C# 함수 오버로딩 예제]
Overload. 오버로드 된 메서드는 코드의 가독성을 높입니다. 프로그램 규모가 커지고 설계가 복잡해질수록 변경되는 코드는 많아집니다. 그래서 코드 변경 지침이 필요하게 됩니다. 「메소드 오버로드를 사용하면」, 복잡성을 줄여 일부 성능을 향상할 수 있습니다.
[객체지향 프로그래밍 oop 다형성 예제]
첫 번째 예제. 오버로딩 함수들은 컴파일된 프로그램에서 독립적입니다. 아래 소스엔 같은 이름을 가진 함수가 2개 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Program { static void Main() { MethodA(); MethodA(""); } static void MethodA() { } static void MethodA(string a) { } } | cs |
두 번째 예제. 위 메소드 예제에는 한 가지 문제가 있습니다. 코드의 가독성과 성능을 향상할 순 있지만, 함수를 호출할 땐 비효율적이고 헷갈릴 수 있습니다.
그래서 string.Empty를 인수로 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using System; class Program { public static void Main() { ShowString(string.Empty); ShowString("Category"); } static void ShowString(string value) { if (value == string.Empty) { Console.WriteLine("Popular"); } else { Console.WriteLine(value); } } } | cs |
[객체지향 프로그래밍 oop 다형성 예제]
세 번째 예제. 위 코드는 불필요한 분기문을 갖고 있습니다. 분기 예측을 위해서라면 아래의 오버로딩 예도 좋을 수 있습니다. (좋을 수도 있지만, 좋지 않을 수도 있다는 중의적 의미)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using System; class Program { public static void Main() { ShowString(); ShowString("Category"); } static void ShowString() { // Send default argument to overload. ShowString("Popular"); } static void ShowString(string value) { // We don't need an if check here, which makes // ... calling this method directly faster. Console.WriteLine(value); } } | cs |
Internals. 오버로딩 된 함수가 컴파일 되는 시점의 중간 언어를 확인합니다. if 문을 가졌던 ShowString 메소드를 살펴봅니다.
[객체지향 프로그래밍 oop 다형성 예제]
오버로드 되지 않았을 경우 : IL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | .method private hidebysig static void ShowString (string 'value') cil managed { // 코드 사이즈 31 (0x1f) .maxstack 8 IL_0000 : ldarg.0 IL_0001 : ldsfld string [mscorlib] System.String :: Empty IL_0006 : call bool [mscorlib] System.String :: op_Equality (string, string) IL_000b : brfalse.s IL_0018 IL_000d : ldstr "Popular" IL_0012 : call void [mscorlib] System.Console :: WriteLine (string) IL_0017 : ret IL_0018 : ldarg.0 IL_0019 : call void [mscorlib] System.Console :: WriteLine (string) IL_001e : ret } | cs |
ShowString의 if 체인 op_Equality가 사용되었습니다. 하지만, JIT (Just in Time) 컴파일 단계에서 최적화 되지 않았습니다.
그럼 메소드가 오버로드된 경우는 어떨까요?
오버로드 사용했을 경우 : IL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 22 (0x16) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: call void OverloadA::ShowString() IL_000b: ldstr "Category" IL_0010: call void OverloadA::ShowString(string) IL_0015: ret } .method private hidebysig static void ShowString() cil managed { // Code size 11 (0xb) .maxstack 8 IL_0000: ldstr "Popular" IL_0005: call void OverloadA::ShowString(string) IL_000a: ret } | cs |
오버로딩된 ShowString 함수는 if else 체인(연관성)이 필요하지 않습니다. 컴파일러가 확인할 필요도 없어서 코드가 효율적입니다. 메서드 오버로드를 사용하기 위해 코드 리펙토링 필요성을 확인할 수 있습니다.
코드 간소화, 성능 향상을 위해 메소드 오버로드가 필요할까요? 네 필요합니다.
덧글. 예제 자체를 이해하는데 시간이 좀 걸렸네요. 참 오묘해요.
C# 메서드 오버로드로 최적화되는지 확인하기 IL
written by vicddory