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
*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