Я наткнулся на случай, который не влияет на мой дизайн, но, скорее всего, повлияет на будущие изменения кода и производительности.C# - Автоматическая инициализация полей класса через конструктор (ручной и динамический)
Мой класс выглядит следующим образом:
public sealed class Commands {
public interface ICommand {
string commandName { get; set; }
}
public ICommand Maintain;
public ICommand Dispatch;
public ICommand Memorize;
//............//
private class ReckonCommand : ICommand {
public string commandName { get; set; }
public ReckonCommand (string name) {
this.commandName = name;
}
}
public Commands() {
Maintain = new ReckonCommand ("Maintain") as ICommand;
Dispatch = new ReckonCommand ("Dispatch") as ICommand;
Memorize = new ReckonCommand ("Memorize") as ICommand;
}
Такой подход потребует вручную инициализации каждой переменной ICommand в классе команд. Таким образом, становится трудно поддерживать, когда поля становятся намного больше.
Альтернативный динамический подход заключается в следующем:
public ICommand Maintain;
public ICommand Dispatch;
public ICommand Memorize;
//............//
private class ReckonCommand : ICommand {
public float commandName { get; set; }
//Stuff
}
public Commands() {
System.Reflection.FieldInfo[] _fields = GetType().GetFields();
for (int i = 0; i < _fields.Length; i++) {
if (_fields [i].FieldType == typeof(ICommand)) {
_fields [i].SetValue (this, new ReckonCommand() as ICommand);
}
}
}
Однако класс команд, как ожидается, будет инициализирован много раз (игнорировать имена, если это мешает вам получить идею), поэтому производительность потеря в какой-то момент может быть эффективной.
Есть ли альтернатива этому конкретному дизайну, который я использую? Моя задача - автоматически инициализировать каждое поле ICommand внутри конструктора класса Commands. Ручной подход подвержен ошибкам, которые могут быть слишком запоздалыми при обнаружении.
Отличная идея, спасибо. Две вещи: i) var, как известно, немного медленнее, чем прямое объявление типа; это потому, что вы не знаете, использую ли я пространства System.Collections.Generic и System.Reflection или это прекрасно в этой ситуации? ii) Как только у вас есть список fieldInfo, метод SetValue так же быстро, как и ваше типичное присвоение значений? Я спрашиваю, потому что интерфейс ICommand также будет иметь метод Modify(). Должен ли я использовать метод SetValue или придумать обходной путь? Modify() будет использоваться гораздо чаще, чем инициализация класса Commands. Cheers –
re var: var - это проблема, связанная с компиляцией, когда компилятор передает тип переменной из присваивания. Это не медленнее во время выполнения, чем явно набирать переменную. Причина, по которой мы его используем, состоит в том, чтобы свести к минимуму количество изменений, необходимых при изменении типа данных. –
re SetValue: он будет немного быстрее и сделает приложение более понятным для использования прямого метода на интерфейсе, а не SetValue. Однако сначала вам нужно заполнить класс Commands действительными экземплярами объектов ICommand, что и делает данный цикл. После того, как у вас есть экземпляр, созданный командой или циклом, вы затем будете использовать методы на интерфейсе ICommand для изменения этого экземпляра (т. Е. Метода Modify). –