ChatGPT解决这个技术问题 Extra ChatGPT

Will using 'var' affect performance?

Earlier I asked a question about why I see so many examples use the varkeyword and got the answer that while it is only necessary for anonymous types, that it is used nonetheless to make writing code 'quicker'/easier and 'just because'.

Following this link ("C# 3.0 - Var Isn't Objec") I saw that var gets compiled down to the correct type in the IL (you will see it about midway down article).

My question is how much more, if any, IL code does using the var keyword take, and would it be even close to having a measurable level on the performance of the code if it was used everywhere?

question answered ages ago, just wanted to add one more thing against var - despite of being resolved at compile time it's not spotted properly by Visual Studio's "Find All References" and Resharper's "Find Usages" if you want to find all usages of the type - and it's not going to be fixed because it would be too slow.
@KolA Variables declared with var most definitely work with "Find All References" in Visual Studio 2019, so if it ever was broken it has been fixed. But I can confirm that it works as far back as Visual Studio 2012, so I'm not sure why you claimed it didn't work.
@Herohtar try following code "class X { } X GetX() { return new X(); } void UseX() { var x = GetX(); }" and Find All References to X , the "var x = GetX()" bit is not highlighted - in latest VS2019 as of now, this is what I meant. It is highlighted though if you use "X x = GetX()" instead of var
@KolA Ah, I see what you mean -- var won't be considered a reference to X when you use "Find All References" on X. Interestingly, if you use "Find All References" on var in that statement, it will show you references to X (though it still won't list the var statement). Additionally, when the cursor is on var, it will highlight all instances of X in the same document (and vice versa).

A
Axel Köhler

There's no extra Intermediate language (IL) code for the var keyword: the resulting IL should be identical for non-anonymous types. If the compiler can't create that IL because it can't figure out what type you intended to use, you'll get a compiler error.

The only trick is that var will infer an exact type where you may have chosen an Interface or parent type if you were to set the type manually.


Not only should the IL be identical - it is identical. var i = 42; compiles to exactly the same code as int i = 42;
@BrianRasmussen: I know your post is old is old, but I assume var i = 42; (infers type is int) is NOT identical to long i = 42;. So in some cases you may be making incorrect assumptions about the type inference. This could cause elusive/edge case runtime errors if the value doesn't fit. For that reason, it may still be a good idea to be explicit when the value doesn't have an explicit type. So for example, var x = new List<List<Dictionary<int, string>()>()>() would be acceptable, but var x = 42 is somewhat ambiguous and should be written as int x = 42. But to each their own...
@NelsonRothermel: var x = 42; isn't ambiguous. Integer literals are of the type int. If you want a literal long you write var x = 42L;.
Uhm what does IL stand for in C#? I never really heard of it.
In your example of the 3 lines of code that behave differently the first line doesn't compile. The second and third lines, which both do compile, do exactly the same thing. If Foo returned a List, rather than an IList, then all three lines would compile but the third line would behave like the first line, not the second.
b
bluish

As Joel says, the compiler works out at compile-time what type var should be, effectively it's just a trick the compiler performs to save keystrokes, so for example

var s = "hi";

gets replaced by

string s = "hi";

by the compiler before any IL is generated. The Generated IL will be exactly the same as if you'd typed string.


s
slavoo

As nobody has mentioned reflector yet...

If you compile the following C# code:

static void Main(string[] args)
{
    var x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

Then use reflector on it, you get:

// Methods
private static void Main(string[] args)
{
    string x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

So the answer is clearly no runtime performance hit!


R
Rob

For the following method:

   private static void StringVsVarILOutput()
    {
        var string1 = new String(new char[9]);

        string string2 = new String(new char[9]);
    }

The IL Output is this:

        {
          .method private hidebysig static void  StringVsVarILOutput() cil managed
          // Code size       28 (0x1c)
          .maxstack  2
          .locals init ([0] string string1,
                   [1] string string2)
          IL_0000:  nop
          IL_0001:  ldc.i4.s   9
          IL_0003:  newarr     [mscorlib]System.Char
          IL_0008:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_000d:  stloc.0
          IL_000e:  ldc.i4.s   9
          IL_0010:  newarr     [mscorlib]System.Char
          IL_0015:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_001a:  stloc.1
          IL_001b:  ret
        } // end of method Program::StringVsVarILOutput

M
Michael Burr

The C# compiler infers the true type of the var variable at compile time. There's no difference in the generated IL.


C
ChrisH

So, to be clear, it's a lazy coding style. I prefer native types, given the choice; I'll take that extra bit of "noise" to ensure I'm writing and reading exactly what I think I am at code/debug time. * shrug *


Thats just your subjective view and not an answer to the question about performance. The right answer is that it has no impact on performance. I voted for close
This doesn't answer the question of whether var affects performance at all; you're just stating your opinion on whether people should use it.
Inferring type from value later, for instance, switching from int 5 to float 5.25, can absolutely cause performance issues. * shrug *
No, that will not cause any performance issues; you'll get build errors in any places that were expecting a variable of type int because it can't automatically convert the float, but that's exactly the same thing that would happen if you explicitly used int and then changed to float. In any case, your answer still does not answer the question of "does using var affect performance?" (particularly in terms of generated IL)
j
jalf

I don't think you properly understood what you read. If it gets compiled to the correct type, then there is no difference. When I do this:

var i = 42;

The compiler knows it's an int, and generate code as if I had written

int i = 42;

As the post you linked to says, it gets compiled to the same type. It's not a runtime check or anything else requiring extra code. The compiler just figures out what the type must be, and uses that.


Right, but what if later you i = i - someVar and someVar = 3.3. i is an Int, now. It's better to be explicit not only to give the compiler a head start on finding flaws, but also to minimize runtime errors or process-slowing type conversions. * shrug * It also makes the code better for self-describing. I've been doing this a long, long time. I'll take "noisy" code with explicit types every time, given the choice.
B
Brian Rudolph

There is no runtime performance cost to using var. Though, I would suspect there to be a compiling performance cost as the compiler needs to infer the type, though this will most likely be negligable.


the RHS has to have its type calculated anyways -- the compiler would catch mismatched types and throw an error, so not really a cost there, I think.
b
bluish

If the compiler can do automatic type inferencing, then there wont be any issue with performance. Both of these will generate same code

var    x = new ClassA();
ClassA x = new ClassA();

however, if you are constructing the type dynamically (LINQ ...) then var is your only question and there is other mechanism to compare to in order to say what is the penalty.


m
mjb

I always use the word var in web articles or guides writings.

The width of the text editor of online article is small.

If I write this:

SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

You will see that above rendered pre code text is too long and flows out of the box, it gets hidden. The reader needs to scroll to the right to see the complete syntax.

That's why I always use the keyword var in web article writings.

var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

The whole rendered pre code just fit within the screen.

In practice, for declaring object, I seldom use var, I rely on intellisense to declare object faster.

Example:

SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject();

But, for returning object from a method, I use var to write code faster.

Example:

var coolObject = GetCoolObject(param1, param2);

If you're writing for students, then eat your own dog food and always write it the same "correct" way, consistently. Students often take things 100% verbatim and to heart, and will begin using any sloppy habits they pick up along the way. $.02
D
Daniel Lorenz

"var" is one of those things that people either love or hate (like regions). Though, unlike regions, var is absolutely necessary when creating anonymous classes.

To me, var makes sense when you are newing up an object directly like:

var dict = new Dictionary<string, string>();

That being said, you can easily just do:

Dictionary<string, string> dict = new and intellisense will fill in the rest for you here.

If you only want to work with a specific interface, then you can't use var unless the method you are calling returns the interface directly.

Resharper seems to be on the side of using "var" all over, which may push more people to do it that way. But I kind of agree that it is harder to read if you are calling a method and it isn't obvious what is being returned by the name.

var itself doesn't slow things down any, but there is one caveat to this that not to many people think about. If you do var result = SomeMethod(); then the code after that is expecting some sort of result back where you'd call various methods or properties or whatever. If SomeMethod() changed its definition to some other type but it still met the contract the other code was expecting, you just created a really nasty bug (if no unit/integration tests, of course).


S
Silvio Garcez

It's depends of situation, if you try use, this code bellow.

The expression is converted to "OBJECT" and decrease so much the performance, but it's a isolated problem.

CODE:

public class Fruta
{
    dynamic _instance;

    public Fruta(dynamic obj)
    {
        _instance = obj;
    }

    public dynamic GetInstance()
    {
        return _instance;
    }
}

public class Manga
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
    public int MyProperty3 { get; set; }
}

public class Pera
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
}

public class Executa
{
    public string Exec(int count, int value)
    {
        int x = 0;
        Random random = new Random();
        Stopwatch time = new Stopwatch();
        time.Start();

        while (x < count)
        {
            if (value == 0)
            {
                var obj = new Pera();
            }
            else if (value == 1)
            {
                Pera obj = new Pera();
            }
            else if (value == 2)
            {
                var obj = new Banana();
            }
            else if (value == 3)
            {
                var obj = (0 == random.Next(0, 1) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance());
            }
            else
            {
                Banana obj = new Banana();
            }

            x++;
        }

        time.Stop();
        return time.Elapsed.ToString();
    }

    public void ExecManga()
    {
        var obj = new Fruta(new Manga()).GetInstance();
        Manga obj2 = obj;
    }

    public void ExecPera()
    {
        var obj = new Fruta(new Pera()).GetInstance();
        Pera obj2 = obj;
    }
}

Above results with ILSPY.

public string Exec(int count, int value)
{
    int x = 0;
    Random random = new Random();
    Stopwatch time = new Stopwatch();
    time.Start();

    for (; x < count; x++)
    {
        switch (value)
        {
            case 0:
                {
                    Pera obj5 = new Pera();
                    break;
                }
            case 1:
                {
                    Pera obj4 = new Pera();
                    break;
                }
            case 2:
                {
                    Banana obj3 = default(Banana);
                    break;
                }
            case 3:
                {
                    object obj2 = (random.Next(0, 1) == 0) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance();
                    break;
                }
            default:
                {
                    Banana obj = default(Banana);
                    break;
                }
        }
    }
time.Stop();
return time.Elapsed.ToString();
}

If you wish execute this code use the code bellow, and get the difference of times.

        static void Main(string[] args)
    {
        Executa exec = new Executa();            
        int x = 0;
        int times = 4;
        int count = 100000000;
        int[] intanceType = new int[4] { 0, 1, 2, 3 };

        while(x < times)
        {                
            Parallel.For(0, intanceType.Length, (i) => {
                Console.WriteLine($"Tentativa:{x} Tipo de Instancia: {intanceType[i]} Tempo Execução: {exec.Exec(count, intanceType[i])}");
            });
            x++;
        }

        Console.ReadLine();
    }

Regards