The generated code (x86) looks like this:
int i = 0;
0000004c xor edx,edx
0000004e mov dword ptr [ebp-4Ch],edx
MessageBox.Show(i++.ToString());
00000051 mov eax,dword ptr [ebp-4Ch]
00000054 mov dword ptr [ebp-54h],eax
00000057 inc dword ptr [ebp-4Ch]
0000005a mov eax,dword ptr [ebp-54h]
0000005d mov dword ptr [ebp-50h],eax
00000060 lea ecx,[ebp-50h]
00000063 call 68C6F120
00000068 mov dword ptr [ebp-58h],eax
0000006b mov ecx,dword ptr [ebp-58h]
0000006e call 67B5DC98
00000073 nop
MessageBox.Show(i++.ToString());
00000074 mov eax,dword ptr [ebp-4Ch]
00000077 mov dword ptr [ebp-5Ch],eax
0000007a inc dword ptr [ebp-4Ch]
0000007d mov eax,dword ptr [ebp-5Ch]
00000080 mov dword ptr [ebp-50h],eax
00000083 lea ecx,[ebp-50h]
00000086 call 68C6F120
0000008b mov dword ptr [ebp-60h],eax
0000008e mov ecx,dword ptr [ebp-60h]
00000091 call 67B5DC98
00000096 nop
array[i++] = Foo;
00000097 mov eax,dword ptr [ebp-4Ch]
0000009a mov dword ptr [ebp-64h],eax
0000009d inc dword ptr [ebp-4Ch]
000000a0 mov eax,dword ptr [ebp-64h]
000000a3 mov edx,dword ptr [ebp-44h]
000000a6 cmp eax,dword ptr [edx+4]
000000a9 jb 000000B0
000000ab call 697AB2C4
000000b0 mov ecx,dword ptr [ebp-48h]
000000b3 mov dword ptr [edx+eax*4+8],ecx
So, no the JIT won't optimise away the variable or it's changes.
The x64 code looks similar. That doesn't optimise away the variable either.