Created
June 6, 2016 12:09
-
-
Save acple/c1d47c97cefdcec0c11e531425e1d4da to your computer and use it in GitHub Desktop.
C#の末尾呼び出し最適化がいろいろおかしいって話
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics; | |
using static System.Console; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// 末尾再帰の検証 .NET framework 4.6.1 / Release_x64 | |
//A(10000000); // -> StackOverflowException!!!! | |
//B(10000000); // -> OK!!!! | |
//C(10000000); // -> ...OK | |
//D(10000000); // -> Infinite Recursion!! | |
//E(10000000); // -> StackOverflowException!!! | |
} | |
public static int A(int x) // 普通の末尾再帰 | |
{ | |
return (x <= 0) ? x : A(x - 1); | |
} // StackOverflowする | |
public static int B(int x) // 普通の末尾再帰の間にWriteLine | |
{ | |
WriteLine(new StackTrace().FrameCount); | |
return (x <= 0) ? x : B(x - 1); | |
} // StackOverflowしない!!!観測者効果かな??? | |
public static int C(int x) // 普通の末尾再帰の間にダミーのnewobj | |
{ | |
var _ = new object(); | |
return (x <= 0) ? x : C(x - 1); | |
} // 何故かStackOverflowしない…… | |
private static readonly int z1 = 0; | |
public static int D(int x) // ただの無限再帰を三項演算子で挟む | |
{ | |
return (z1 == 0) ? D(x) : D(x); | |
} // ちゃんと無限ループになる == 末尾呼び出しの最適化が効いてる | |
private const int z2 = 0; | |
public static int E(int x) // ただの無限再帰を条件がコンパイル時に確定するような三項演算子で挟む | |
{ | |
return (z2 == 0) ? E(x) : E(x); | |
} // StackOverflowする 条件項に true or false でも同様に死亡 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment