Clojure má konstrukci loop-recur (případně se používá trampoline) právě pro to, že JVM neumožňuje tail-call optimalizaci. Na druhou straunu překladač Scaly, která taky běží nad JVM, to "umí" - tím, že z toho udělá cyklus.
Jestli je to možné u C# 5, to se přiznám, že nevím - překladač verze 4 to neumí byť .Net to podporuje. C/C++ u novějších překladačů (jak Microsoft tak GCC) to umí a nedávno jsem to viděl i u free pascalu. Nicméně často se musí explicitně zapnout.
Každopádně i když rekurze je ve funkcionálních (a logických) jazycích celkem často k vidění, v imperativních jazycích není až tak potřeba - stejně je většinou pohodlnější tu danou věc zapsat cyklem než rekurzí.