#c# #reflection
#c# #отражение
Вопрос:
Когда я получаю доступ к своим Operation
классам извне, я использую отражение, чтобы задать их полям массив значений. Это потому, что он лучше подходит для целей автоматизации.
При доступе изнутри (см. Метод Calculate
) я хочу использовать поля по имени для лучшей читаемости. Количество полей варьируется в зависимости от разных классов, производных от Operation
.
Есть ли более быстрый способ сделать это, чем с помощью отражения?
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 resu<
}
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();
Комментарии:
1. вы используете 2 объекта, о которых мы ничего не знаем
2. Вам не нужно.
3. Как насчет порядка расположения ваших элементов? Компилятор ничего не гарантирует в этом вопросе.
4. @thehenny: верно, но порядок подхода к отражению не имеет значения, верно? Это было бы ограничивающим фактором для подхода, записывающего более или менее непосредственно в память. Это то, что вы хотите указать?
5. что ж, если вам нужно, чтобы кто-то проанализировал то, что вы сделали, тогда они также должны знать остальные эти объекты. поскольку ваша структура может не требовать отражения, и, как правило, если вы используете отражение, есть другие способы добиться того же
Ответ №1:
Короткий ответ: Да.
Более длинный ответ: Это зависит. Как часто это делается? Если это выполняется много-много раз за время существования приложения, то есть более быстрые способы, чем отражение: либо использовать деревья выражений (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees /) или для этого испускать IL во время выполнения.
Однако стоимость компиляции дерева выражений (или функции IL) для повторного использования довольно высока. Если вы делаете это один раз в начале жизненного цикла приложения или если appdomain недолговечен (например, консольное приложение, которое запускается каждые несколько минут), то стоимость доступа значительно уменьшается по сравнению с затратами на запуск.
Комментарии:
1. Что ж, я мог бы легко позволить себе скомпилировать что-то для ограниченного числа «Операционных» классов при запуске приложения. На данный момент частота соответствующих вычислений относительно низкая, поэтому мне, вероятно, не нужно ускоряться. Но проект, над которым я работаю, несколько раз подвергался некоторому расширению области видимости, поэтому теперь я хочу быть готовым к более высоким вычислительным требованиям в будущем и принять правильное проектное решение сейчас. Можете ли вы дать приблизительную цифру о том, сколько еще кода потребуется, чтобы сделать это с деревьями выражений? Два раза? Десять раз? Насколько быстрее это, вероятно, было бы?
2. Дело не столько в том, насколько больше кода, сколько в том, что нужно думать по-другому. Хотя это правда, что вам понадобится больше кода для выполнения тех же операций. Что касается производительности, она, как правило, на несколько порядков выше, чем отражение, вот относительно старое сравнение: codewrecks.com/blog/index.php/2008/10/04/… В нем также есть несколько примеров кода, хотя форматирование блога изменилось и может быть трудным для чтения.
3. Я просмотрел ссылку codewrecks. Похоже, это ответ на мой вопрос, но мне придется подождать, пока я не найду время реализовать его для моего варианта использования. Я все равно отмечаю ответ как принятый.
4. Имейте в виду, что типы значений и ссылочные типы могут сильно отличаться, когда вы имеете дело с некоторыми базовыми данными, особенно если вы используете исходящий IL. Если пример кода не работает для вас, возможно, это причина.
5. Спасибо, в моем случае меня интересуют только ссылочные типы. Но приятно знать, что некоторые отлаживают. Требуются утверждения.