Don’t use var, it’s zashkvar

Task: to verify the truth of this statement, to abstract from physical violence.

As follows from C# language guides:

Variables declared in method scope can have an implicit “type”. var An implicitly typed local variable is strongly typed as if you had declared the type yourself, but the compiler infers the type.

The manual also states that ads

var a = 10; // Implicitly typed.
int b = 10; // Explicitly typed.

functionally equivalent.

But what do they understand, these scribblers, unlike people who have *-tsat years of development experience!

To heighten the effect, let’s imagine for the time of reading the article that we are fools. You can turn on Morgenstern in the background.

What to understand:

  1. Differences in IL code

  2. Memory layout

  3. What is “slow”

IL code

For example, let’s take value and reference types, declare them with var and without.

int i = 45;
var i1 = 45;

object o = 45;
var o1 = (object)45;

List<string> l = new List<string>();
var l1 = new List<string>();

object ol = new List<string>();
var ol1 = new List<string>();

We collect, open in dotPeek, we see the following picture in the IL code:

// [9 7 - 9 18]
IL_0001: ldc.i4.s     45 // 0x2d
IL_0003: stloc.0      // i

// [10 7 - 10 19]
IL_0004: ldc.i4.s     45 // 0x2d
IL_0006: stloc.1      // i1

…

// [15 7 - 15 21]
IL_0013: ldc.i4.s     45 // 0x2d
IL_0015: box          [System.Runtime]System.Int32
IL_001a: stloc.s      o

// [16 7 - 16 27]
IL_001c: ldc.i4.s     45 // 0x2d
IL_001e: box          [System.Runtime]System.Int32
IL_0023: stloc.s      o1

For the first declarations of variables i and i1, we see the same opcodes ldc.i4.s and stloc, and for declarations o and o1, box and stloc.s are added through object, what does it all mean?

Opcode ldc.i4.s pushes a value of type int onto the stack (in general, it pushes int8 like int32, but I don’t want to be boring).

Opcode stloc pops the top value of the stack and pushes it into the list of local variables (.0 and .1 point to the index in the list of local variables).

But for object has already been added package the value originally placed, and the opcode stloc.s, well, it’s understandable, the type is a reference. The same opcode can be seen in the listing for the List type.

As you can see, the type declaration through int and var similar to it generated the same code, in which the object does not smell when using var.

For a complete picture, I will attach a notarized screenshot.

C# and IL code of the decompiled assembly
C# and IL code of the decompiled assembly

Mom’s skill sharpists will immediately say that I don’t understand anything in development. And generally speaking. It remains only to turn up the volume of the next Morgenstern track and go explore the memory.

Memory layout

The IL code may be the same, but what if it is placed differently in memory? For example, var is allocated on the heap, not on the stack. Let’s look at the non-IL code, well, in memory, of course.

Let’s open the disassembled code in the Visual Studio debugger.

     9:       int i = 45;
00007FFC03D90FE6  mov         dword ptr [rbp+84h],2Dh  
    10:       var i1 = 45;
00007FFC03D90FF0  mov         dword ptr [rbp+80h],2Dh  
    11: 
    12:       object o = 45;
00007FFC03D90FFA  mov         rcx,7FFC03D5B1F0h  
00007FFC03D91004  call        CORINFO_HELP_NEWSFAST (07FFC638B7840h)  

…

    13:       var o1 = (object)45;
00007FFC03D91020  mov         rcx,7FFC03D5B1F0h  
00007FFC03D9102A  call        CORINFO_HELP_NEWSFAST (07FFC638B7840h) 

So, what do we see here? For var and int, the code executed by the processor is identical, in memory at the address in the RBP register, with some offset, the value 2D (45 in decimal notation) is placed. The dword type tells us it’s 4 bytes. That’s right, the int type is 4 bytes.

Let’s look at memory! To do this, enter &i in the interpretation window. The address where the value of the variable is located will be displayed. The same for i1. By the way, in the listing above you can see that the values ​​are placed one after another, first i1, after 4 bytes i.

The screenshot is not certified, the notary went to lunch
The screenshot is not certified, the notary went to lunch

Going to the address of the i1 variable, we see:

0x0000007133B7E5E0  2d 00 00 00 2d 00 00 00

Our dear bytes, lie, miss. And what about object? Enter &o and &o1 in the interpretation window. As you can see from the listing, placing variables of type object works differently, through a call to CORINFO_HELP_NEWSFAST.

0x0000007133B7E5D0  b8 ac 0f cc 13 02 00 00

Nothing similar to 2D was found in memory. The value stored for object is the address of the object on the heap. Let’s take a snapshot of the memory, let’s see what we have in the heap! And in the heap, sorry for the tautology, a lot of objects. We are interested in Ints. If you switch to the view of instances, you can see the objects and their addresses given earlier in the interpretation window.

Process memory snapshot
Process memory snapshot
An address in memory points to an object on the heap
An address in memory points to an object on the heap

What follows from all this?

  1. Using var and an explicit type declaration gives the same result

  2. Objects are stored in memory according to the same rules. Significant ones are on the stack, reference ones are on the heap. No exceptions, whether it is declared as var, or Ivan Fedorovich Kruzenshtern.

Performance

I don’t see much point in doing any research in terms of speed, since placement and typing are absolutely identical, from which I conclude that operations with types in both cases will be equivalent in speed.

In light of the foregoing, the only performance-relevant factor to pay close attention to is the performance of dodging the poke when saying “var is slow”.

On this, the research is completed, we take out the shotgun, forcibly (almost like kill -9) turn off Morgenstern. Smoothly return to the resource state.

PS Challenge for Mom’s Sharpists – write an article about why I’m wrong, with research and proofs. Screenshots at the notary can not be certified, he is still having lunch.

Similar Posts

Leave a Reply