I came back from the Lang.NET conference and spoke to members of the C# team about two features which are exposed in IL, but are not available in C#.
1) Extended precision for floating-point calculations.
2) Tail call optimizations.
In C++, intermediate calculations can be performed at the highest precision offered by hardware. In C#, intermediate calculations with doubles are fixed at the standard or double precision--the precision of a double data type. The same is possibly true for floats. Double precision is not large enough to store a long value. The rationale is to prevents errors in which same code yields different results depending on optimization settings and environment.
Tail call optimizations arise when the result of a function call is directly returned without any intervening operations. The new function call reuses the caller’s stack frame and it’s use is not limited to tail recursion scenarios.
Tail calls are currently used by F# and Nemerle. C# programs benefit from tail call optimization in 64-bit architectures as tail calls are aggressively performed regardless of the presence of the .tail prefix. In 64-bit, the limited stack space is depleted much more quickly. Tail call optimization is turned off during debugging.
Because of the existing optimization in 64-bit, it seems harmless that the C# could automatically insert tail calls into the compiler in the VS 2010 timeframe. This would encourage programming in a more functional style. (Actually, tails calls are somewhat slower in x86.)
In my own development, I hit upon the stack limit through finite recursion and had to double the amount of stack space in my thread.
My current approach for dealing with these two problems is to disassemble my executable with ILDASM, insert the .TAIL prefix, remove the CONV.R8 or CONV.R4 instructions, and rebuild the executable with ILASM.
Some tail call links:
http://blogs.msdn.com/davbr/pages/tail-call-jit-conditions.aspx
https://beta.blogs.msdn.com/shrib/archive/2005/01/25/360370.aspx
So what are your current work Wes? Is NStatic still in the pipe?
Another cool IL thing C# doesn't have: the visibility level: internal AND protected (we currently only have internal OR protected)
Another one:the possibility to base enum on a float or double.
Posted by: Patrick Smacchia | April 20, 2009 at 05:51 AM
Patrick, I spoke at Lang.NET last week. The video should be out, although there is no demo.
Posted by: Wes | April 20, 2009 at 06:02 AM
The other biggie is exception filters. VB.NET exposes them, C# doesn't, and the BCL uses them internally (by writing a helper in VB.NET).
Posted by: Daniel Earwicker | April 20, 2009 at 08:43 AM
@Daniel,
I wouldn’t say that C# ‘misses’ exception filters. Besides, they present subtleties of their own. Exceptions thrown from a filter (i.e.: with NullReferenceExceptions) are swallowed and the filter evaluates as false.
Posted by: Steven | April 20, 2009 at 12:14 PM
Do you try Reflector?
Posted by: Jack | April 22, 2009 at 02:40 AM
Regarding reflector,
http://geekswithblogs.net/jwhitehorn/archive/2007/06/06/113060.aspx
While using reflector, I haven't seen a case where the tail call prefix has been used in the IL generated by C#; and there are many such instances where that would be possible (for example, a void function which is the last statement of a calling void function).
The C# PM Luke Hoban incorrectly states that there are few instances where the tail call would be applied in practice; I believe that he may simply be thinking of tail recursion.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=166013&wa=wsignin1.0
Posted by: Wes | April 22, 2009 at 06:51 AM
@Steven: "I wouldn’t say that C# ‘misses’ exception filters."
It seems the BCL team disagrees with you, then! I certainly do. There is no fundamental reason why it makes sense to only filter exceptions by their location in an inheritance hierarchy, especially with the limitation of single inheritance and the fact that the BCL has no rational hierarchy to its exceptions (nor is there necessarily any way to impose one even if you began from scratch).
Obviously it is necessary to define sensible behaviour for filters if they throw - this does not in any way change their essential usefulness when they don't.
Posted by: Daniel Earwicker | April 27, 2009 at 02:38 PM