Been a while (years) since I've looked at assembly, and I know close to nothing about MSIL and JIT, so it would be a nice exercise - couldn't resist, so here's just a bit of, possibly redundant, empirical data. Does the IndexOf
overload get inlined?
Here's a tiny Console app:
class Program
{
static void Main(string[] args)
{
"hello".Contains("hell");
}
}
The JIT generates this in an optimized Release build, Any CPU, running in 32 bit. I've shortened the addresses, and removed some irrelevant lines:
--- ...\Program.cs
"hello".Contains("hell");
[snip]
17 mov ecx,dword ptr ds:[0320219Ch] ; pointer to "hello"
1d mov edx,dword ptr ds:[032021A0h] ; pointer to "hell"
23 cmp dword ptr [ecx],ecx
25 call 680A6A6C ; String.Contains()
[snip]
The call
at 0x00000025 goes here:
String.Contains
00 push 0 ; startIndex = 0
02 push dword ptr [ecx+4] ; count = this.Length (second DWORD of String)
05 push 4 ; comparisonType = StringComparison.Ordinal
07 call FF9655A4 ; String.IndexOf()
0c test eax,eax
0e setge al ; if (... >= 0)
11 movzx eax,al
14 ret
Sure enough, it seems to call, directly, the final String.IndexOf
overload with four arguments: three push
ed; one in edx
(value
: "hell"); this
("hello") in ecx
. To confirm, this is where the call
at 0x00000005 goes:
00 push ebp
01 mov ebp,esp
03 push edi
04 push esi
05 push ebx
06 mov esi,ecx ; this ("hello")
08 mov edi,edx ; value ("hell")
0a mov ebx,dword ptr [ebp+10h]
0d test edi,edi ; if (value == null)
0f je 00A374D0
15 test ebx,ebx ; if (startIndex < 0)
17 jl 00A374FB
1d cmp dword ptr [esi+4],ebx ; if (startIndex > this.Length)
20 jl 00A374FB
26 cmp dword ptr [ebp+0Ch],0 ; if (count < 0)
2a jl 00A3753F
[snip]
... which would be the body of:
public int IndexOf(string value,
int startIndex,
int count,
StringComparison comparisonType)
{
if (value == null)
throw new ArgumentNullException("value");
if (startIndex < 0 || startIndex > this.Length)
throw new ArgumentOutOfRangeException("startIndex",
Environment.GetResourceString("ArgumentOutOfRange_Index"));
if (count < 0 || startIndex > this.Length - count)
throw new ArgumentOutOfRangeException("count",
Environment.GetResourceString("ArgumentOutOfRange_Count"));
...
}