Skip to content

Instantly share code, notes, and snippets.

@acple
Created June 6, 2016 12:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acple/c1d47c97cefdcec0c11e531425e1d4da to your computer and use it in GitHub Desktop.
Save acple/c1d47c97cefdcec0c11e531425e1d4da to your computer and use it in GitHub Desktop.
C#の末尾呼び出し最適化がいろいろおかしいって話
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