配列の長さをC#のローカル変数に保存する価値はありますか?

多くの場合、人々は次のように書いていることに気づきます。



var length = array.Length;
for (int i = 0; i < length; i++) {
    //do smth
}
      
      





, CLR Array.Length. .



C#:



public int WithoutVariable() {
    int sum = 0;
    for (int i = 0; i < array.Length; i++) {
        sum += array[i];
    }
    return sum;
}
public int WithVariable() {
    int sum = 0;
    int length = array.Length;
    for (int i = 0; i < length; i++) {
        sum += array[i];
    }
    return sum;
}
      
      





, JIT .NET Framework 4.7.2 LegacyJIT-x86:

WithoutVariable()

;int sum = 0;

    xor  edi, edi

;int i = 0;

    xor  esi, esi

;int[] localRefToArray = this.array;

    mov  edx, dword ptr [ecx+4]

;int arrayLength = localRefToArray.Length;

    mov  ecx, dword ptr [edx+4]

;if (arrayLength == 0) return sum;

    test ecx, ecx

    jle  exit

;int arrayLength2 = localRefToArray.Length;

    mov  eax, dword ptr [edx+4] 

;if (i >= arrayLength2)

;  throw new IndexOutOfRangeException();

  loop:

    cmp  esi, eax

    jae  056e2d31

;sum += localRefToArray[i];

    add  edi, dword ptr [edx+esi*4+8]

;i++;

    inc  esi

;if (i < arrayLength) goto loop

    cmp  ecx, esi

    jg  loop

;return sum;

  exit:

    mov  eax, edi
WithVariable()

;int sum = 0;

    xor  esi, esi

;int[] localRefToArray = this.array;

    mov  edx, dword ptr [ecx+4]

;int arrayLength = localRefToArray.Length;

    mov  edi, dword ptr [edx+4]

;int i = 0;

    xor  eax, eax

;if (arrayLength == 0) return sum;

    test edi, edi

    jle  exit

;int arrayLength2 = localRefToArray.Length;

    mov  ecx, dword ptr [edx+4]

;if (i >= arrayLength2)

;  throw new IndexOutOfRangeException();

  loop:

    cmp  eax, ecx

    jae  05902d31

;sum += localRefToArray[i];

    add  esi, dword ptr [edx+eax*4+8]

;i++;

    inc  eax

;if (i < arrayLength) goto loop

    cmp  eax, edi

    jl   loop

;return sum;

  exit:

    mov  eax, esi


Meld




, — 15 . . . , :





, , .



:



public int WithoutVariable() {
    int sum = 0;
    for(int i = 0; i < array.Length; i++) {
        sum += array[i] + array.Length;
    }
    return sum;
}

public int WithVariable() {
    int sum = 0;
    int length = array.Length;
    for(int i = 0; i < length; i++) {
        sum += array[i] + length;
    }
    return sum;
}
      
      





, , . :

WithoutVariable()

int sum = 0;

    xor  edi, edi

int i = 0

    xor  esi, esi

int[] localRefToArray = this.array

    mov  edx, dword ptr [ecx+4]

int arrayLength = localRefToArray.Length

    mov  ebx, dword ptr [edx+4]

if (arrayLength == 0) return sum;

    test ebx, ebx

    jle  exit

int arrayLength2 = localRefToArray.Length;

    mov  ecx, dword ptr [edx+4]

if (i >= arrayLength2)

  throw new IndexOutOfRangeException()

  loop:

    cmp  esi, ecx 

    jae  05562d39

int t = array[i]

    mov  eax, dword ptr [edx+esi*4+8]

+= sum;

    add  eax, edi

t+= arrayLength;

    add  eax, ebx

sum = t

    mov  edi, eax

i++;

    inc  esi

if (i < arrayLength) goto loop

    cmp  ebx, esi

    jg   loop

return sum;

  exit:

    mov  eax, edi

WithVariable()

int sum = 0;

    xor  esi, esi

int[] localRefToArray = this.array;  

    mov  edx, dword ptr [ecx+4]

int arrayLength = localRefToArray.Length;  

    mov  ebx, dword ptr [edx+4]

int i = 0;  

    xor  ecx, ecx

if (arrayLength == 0) (return sum;) 

    test  ebx, ebx

    jle  exit

int arrayLength2 = localRefToArray.Length;

    mov   edi, dword ptr [edx+4]

if (i >= arrayLength2)

 throw new IndexOutOfRangeException();

 loop:

    cmp  ecx, edi

    jae  04b12d39

int t = array[i]

    mov  eax, dword ptr [edx+ecx*4+8]

+= sum

    add  eax, esi

t+= arrayLength

    add  eax, ebx

sum = t

    mov  esi, eax

i++

    inc  ecx

if (i < arrayLength) goto loop 

    cmp  ecx, ebx

    jl   loop

return sum;

  exit:

    mov  eax, esi



Meld




, . , sum array.Length, . :

int arrayLength2 = localRefToArray.Length;

    mov     edi, dword ptr [edx+4]

if (i >=arrayLength2) throw new IndexOutOfRangeException();

    cmp     ecx, edi

    jae     04b12d39
— .



, , .. . .



ForEach. :



public int ForEachWithoutLength() {
    int sum = 0;
    foreach (int i in array) {
        sum += i;
    }
    return sum;
}

public int ForEachWithLengthWithoutLocalVariable() {
    int sum = 0;
    foreach (int i in array) {
        sum += i + array.Length;
    }
    return sum;
}

public int ForEachWithLengthWithLocalVariable() {
    int sum = 0;
    int length = array.Length;
    foreach (int i in array) {
        sum += i + length;
    }
    return sum;
}
      
      





JIT:



ForEachWithoutLength()
;int sum = 0;

    xor  esi, esi

;int[] localRefToArray = this.array; 

    mov  ecx, dword ptr [ecx+4]

;int i = 0;

    xor  edx, edx

;int arrayLength = localRefToArray.Length; 

    mov  edi, dword ptr [ecx+4]

;if (arrayLength == 0) goto exit;

    test  edi, edi

    jle  exit

;int t = array[i];

  loop:

    mov  eax, dword ptr [ecx+edx*4+8]

;sum+=i;

    add  esi, eax

;i++;

    inc  edx

;if (i < arrayLength) goto loop

    cmp  edi, edx

    jg  loop

;return sum;

  exit:

    mov  eax, esi


ForEachWithLengthWithoutLocalVariable()
;int sum = 0;

    xor  esi, esi

;int[] localRefToArray = this.array;  

    mov  ecx, dword ptr [ecx+4]

;int i = 0; 

    xor  edx, edx

;int arrayLength = localRefToArray.Length;  

    mov  edi, dword ptr [ecx+4]

;if (arrayLength == 0) goto exit

    test  edi, edi

    jle  exit

;int t = array[i];  

  loop:

    mov  eax, dword ptr [ecx+edx*4+8]

;sum+=i; 

    add  esi, eax

;sum+=localRefToArray.Length;

    add  esi, dword ptr [ecx+4]

;i++;

    inc  edx

;if (i < arrayLength) goto loop 

    cmp  edi, edx

    jg  loop

;return sum;

  exit:

    mov  eax, esi


ForEachWithLengthWithLocalVariable()
;int sum = 0;

    xor  esi, esi

;int[] localRefToArray = this.array;   

    mov  edx, dword ptr [ecx+4]

;int length = localRefToArray.Length;   

    mov  ebx, dword ptr [edx+4]

;int i = 0;  

    xor  ecx, ecx

;int arrayLength = localRefToArray.Length;   

    mov  edi, dword ptr [edx+4]

;if (arrayLength == 0) goto exit; 

    test  edi, edi

    jle  exit

;int t = array[i];  

  loop: 

    mov  eax, dword ptr [edx+ecx*4+8]

;sum+=i;  

    add  esi, eax

;sum+=length ; 

    add  esi, ebx

;i++; 

    inc  ecx

;if (i < arrayLength) goto loop

    cmp  edi, ecx

    jg  loop

;return sum;

  exit:

    mov  eax, esi


, , for ( foreach 12 , for 15).



For ForEach




, for vs foreach 1 000 000 ,



sum+=array[i];
      
      



Method ItemsCount Mean Error StdDev Median Ratio RatioSD
ForEach 1000000 1.401 ms 0.2691 ms 0.7935 ms 1.694 ms 1.00 0.00
For 1000000 1.586 ms 0.3204 ms 0.9447 ms 1.740 ms 1.23 0.65




sum+=array[i] + array.Length;
      
      



Method ItemsCount Mean Error StdDev Median Ratio RatioSD
ForEach 1000000 1.703 ms 0.3010 ms 0.8874 ms 1.726 ms 1.00 0.00
For 1000000 1.715 ms 0.2859 ms 0.8430 ms 1.956 ms 1.13 0.56
ForEach For. ? JIT.



foreach




ForEachWithoutLength. . ForEach - , - . - JIT .



ForEachWithLengthWithoutLocalVariable. , sum+=length arrayLength, , . , N + 1, N — .



ForEachWithLengthWithLocalVariable. ForEachWithLengthWithoutLocalVariable, . arrayLength, , length . , . .



. , , , : . , , Foreach For.



All Articles