Home > Back-end >  Inside a method is it the same to assign the return value to a variable first and then return it, wi
Inside a method is it the same to assign the return value to a variable first and then return it, wi

Time:08-03

a)

public static List<T> Search()
{
   var test = GetList<T>(); // Potentially returning a huge number of objects
   return test;
}

b)

public static List<T> Search() => GetList<T>();

Does assigning first a big number of objects to a list variable, like in first case, has any impact in performance (memory,speed etc)?

My problem is that I want to measure the execution time of GetList(), without changing its code (don't have access to it) and without doing it in every reference of search. Thus, I am thinking of doing the below, but need to be sure that it won't have any negative impact anyhow:

public static List<T> Search()
{
   var time = Stopwatch.StartNew();
   var test = GetList<T>(); // Returns a huge number of objects
   
   Log($"Execution time: {time.ElapsedMilliseconds}");
  
   return test;
}

The code is for making the question clearer (if that is possible).

CodePudding user response:

Variables in C# are basically references so it doesn't matter how many objects GetList() returns, only a reference to the list will be passed around. This alone will make the code practically equivalent in terms of performance. Even more in release mode the 2 snippets compile to the same IL:

 .method public hidebysig static 
        class [System.Collections]System.Collections.Generic.List`1<!!T> Search_1<T> () cil managed 
    {
        // Method begins at RVA 0x205c
        // Code size 6 (0x6)
        .maxstack 8

        IL_0000: call class [System.Collections]System.Collections.Generic.List`1<!!0> C::GetList<!!T>()
        IL_0005: ret
    } // end of method C::Search_1

    .method public hidebysig static 
        class [System.Collections]System.Collections.Generic.List`1<!!T> Search_2<T> () cil managed 
    {
        // Method begins at RVA 0x2063
        // Code size 6 (0x6)
        .maxstack 8

        IL_0000: call class [System.Collections]System.Collections.Generic.List`1<!!0> C::GetList<!!T>()
        IL_0005: ret
    } // end of method C::Search_2

CodePudding user response:

As bolov said in their answer it doesn't matter. And to expand on that, you can use a tool like sharplab to take a look at what code actually gets compiled (after syntactic desugaring) as well as take a look at the IL and even the actual JIT Asm generated, doing this with your example shows me that both examples are compiled to the exact same thing*

You can check the decompile C# here and the compiled IL here, I'll copy and paste the relevant parts of the IL here though:

(make sure to set sharplab to release mode)

    .method public hidebysig 
        instance class [System.Private.CoreLib]System.Collections.Generic.List`1<!T> SearchAssign () cil managed 
    {
        // Method begins at RVA 0x2057
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance class [System.Private.CoreLib]System.Collections.Generic.List`1<!0> class Class`1<!T>::GetList()
        IL_0006: ret
    } // end of method Class`1::SearchAssign

    .method public hidebysig 
        instance class [System.Private.CoreLib]System.Collections.Generic.List`1<!T> SearchDirect () cil managed 
    {
        // Method begins at RVA 0x2057
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance class [System.Private.CoreLib]System.Collections.Generic.List`1<!0> class Class`1<!T>::GetList()
        IL_0006: ret
    } // end of method Class`1::SearchDirect

(diffchecker to illustrate)

*Well, technically a) is a method and b) is a property, but converting b) to a method shows this, plus the IL for a), b) and the method form of b) are exactly the same

  • Related