Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Foreach optimisation with reflection

Basically, is this code segment:

// Get these once, create list, re-use same list
var prodType = products.GetType();
var fieldInfList = prodType.GetFields();
var propInfList = prodType.GetProperties();

foreach (var p in products)
{
    foreach (var fieldInf in fieldInfList)
    {
        fieldInf.SetValue(this, fieldInf.GetValue(p));
    }
    foreach (var propInf in propInfList)
    {
        propInf.SetValue(this, propInf.GetValue(p));
    }
}

faster than this:

foreach (var p in products)
{
    foreach (var fieldInf in products.GetType().GetFields())
    {
        fieldInf.SetValue(this, fieldInf.GetValue(p));
    }
    foreach (var propInf in products.GetType().GetProperties())
    {
        propInf.SetValue(this, propInf.GetValue(p));
    }
}

...?

My thinking is that with the second block each loop will do the work of inspecting the object again, whereas the first will have on list that will persist for each loop.

Similarly with the line

var prodType = products.GetType();

the type will only be retrieved once.

Or does the compiler / .Net just re-use the same list in the second example without me having to do anything? How do I compare the overhead of creating a new list with getting the object properties repeatedly? Would the garbage collector treat my created list any differently causing it to hang around longer?

Any answer or pointing in the right direction is much appreciated.

like image 288
MattMcGowan Avatar asked Jan 31 '26 01:01

MattMcGowan


1 Answers

Or does the compiler / .Net just re-use the same list in the second example without me having to do anything?

If it knew that the Reflection APIs are idempotent and the resulting objects are observationally pure it could do that. It does not know that. This optimization will not be done. Calling any of the Reflection APIs could print to the console in theory. The JIT must execute the calls to be sure.

In fact, even then it's not a safe optimization because the Reflection API might throw and that exception will only be raised if the outer loop does at least one iteration.

Yes, factoring out the list will result in a performance increase.

How do I compare the overhead of creating a new list with getting the object properties repeatedly?

Nor sure what you mean. Measure.

Would the garbage collector treat my created list any differently causing it to hang around longer?

This has no effect on the GC to speak of because the list of properties is tiny (probably a few hundreds of bytes depending on the number of properties).

I guess factoring out the list would result in that list being kept alive a tiny bit longer because the lists will stay alive until the outer loop is completed (in the current implementation of the CLR at least).

like image 64
usr Avatar answered Feb 02 '26 14:02

usr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!