A comment buried in some C++ code in the SSCLI claims, referring to the unmanaged internal implementation of String.Chars property:
This method is not actually used. JIT will generate code for indexer method on string class.
So...what magical code is this? I understand the whole point of jitters is that they produce different code in different situations. But at the very least, for a modern x64 Windows 7+ platform, how might the/a jitter accomplish this? Or is that truly secret sauce?
Additional details
A while ago I was looking for the fastest way to iterate through individual characters in a string in C#.
It turned out the fastest way without resorting to unsafe code or duplicating the contents (via ToCharArray()
)
was the built-in string indexer, which is actually a call to the String.Chars property. Right in my original
question I asked if anyone had insight into how the indexer actually worked, but despite bumps from both Skeet and
Lippert, I didn't get any responses on that. So I decided to dig into it myself:
Stop 1: mscorlib
By examining mscorlib.dll with ildasm, we can see that String::get_Chars(int32 index)
is just an internalcall
pointer (plus an attribute):
.method public hidebysig specialname instance char
get_Chars(int32 index) cil managed internalcall
{
.custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
} // end of method String::get_Chars
As noted in the documentation for the MethodImplOptions enumeration, "An internal call is a call to a method that is implemented within the common language runtime itself." Both a 2004 MSDN Magazine article and an SO post indicate that the mapping of internalcall
names to unmanaged implementations can be found in ecall.cpp within the Shared Source CLI.
Stop 2: ecapp.cpp
Searching an online copy of ecall.cpp reveals that get_Chars
is implemented by COMString::GetCharAt
:
FCIntrinsic("get_Chars", COMString::GetCharAt, CORINFO_INTRINSIC_StringGetChar)
Stop 3: comstring.cpp
comstring.cpp does indeed contain an implementation of GetCharAt, starting at line 1219. Except, it's preceded by this comment:
/*==================================GETCHARAT===================================
**Returns the character at position index. Thows IndexOutOfRangeException as
**appropriate.
**This method is not actually used. JIT will generate code for indexer method on string class.
**
==============================================================================*/