oliver
oliver

Reputation: 2901

Setting/getting fields of a class with an array: faster way than reflection?

When I access my Operation classes from the outside, I am using reflection to set their fields with an array of values. This is because it lends itself better to automation purposes.

When accessed from the inside (see method Calculate), I want to use the fields by name for the sake of better readability. The number of fields varies between different classes derived from Operation.

Is there a faster way to do this than by reflection?

public abstract class Operation
{
    readonly FieldInfo[] inputFields;

    public int InputCount {get {return inputFields.Length;}}

    public Cacheable[] InputData
    {
        get 
        {
            Cacheable[] result = new Cacheable[inputFields.Length];

            for (int i=0; i<inputFields.Length; i++)
            {
                result[i] = (Cacheable)inputFields[i].GetValue(this);
            }

            return result;
        }
        set 
        {
            for (int i=0; i<inputFields.Length; i++)
            {
                inputFields[i].SetValue(this, value[i]);
            }
        }
    }

    public Operation()
    {
        FieldInfo[] inputFields = GetType().GetFields();
    }

    public abstract void Calculate();
}

public class OperationA: Operation
{
    public CacheableU SomeField;
    public CacheableV AnotherField;

    public override void Calculate()
    {
        DoSomething(SomeField, AnotherField);
    }
}   

public class OperationB: Operation
{
    public CacheableU SomeField;
    public CacheableV AnotherField;
    public CacheableW YetAnotherField;

    public override void Calculate()
    {
        DoSomethingElse(SomeField, AnotherField, YetAnotherField);
    }
}

// ...
Cacheable[] inputsToA = new[]{c1, c2};
OperationA opa = new OperationA();
opa.InputData = inputsToA;
opa.Calculate();

Cacheable[] inputsToB = new[]{c3, c4, c5};
OperationB opb = new OperationB();
opb.InputData = inputsToB;
opb.Calculate();

Upvotes: 0

Views: 65

Answers (1)

willaien
willaien

Reputation: 2797

Short answer: Yes.

Longer answer: It depends. How often is this being done? If it's being done many many times over the lifetime of the application, then there are faster ways than reflection: either use expression trees (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/) or emit IL at runtime to do this.

However, the cost of compiling the expression tree (or IL function) for re-use is fairly high. If you are doing this once at the beginning of the application's lifecycle, or if the appdomain is short-lived (eg. console application that runs every few minutes), then the cost per access is greatly dwarfed by the startup costs.

Upvotes: 3

Related Questions