Я хочу получить доступ к трем членам класса (_orderDay, _orderCustody, _orderBox) в соответствии с переменной индексации (orderIndex), используя другой подход, чем в следующем примере.
public class COrdering
{
private int _orderDay;
private int _orderCustody;
private int _orderBox;
public COrdering() { _orderDay = _orderCustody = _orderBox = 0; }
public int IncOrder(int orderIndex)
{
int v = orderIndex == 0 ? _orderDay : (orderIndex == 1 ? _orderCustody : _orderBox);
v++;
if (orderIndex == 0) _orderDay = v
else if (orderIndex == 1) _orderCustody = v;
else _orderBox = v;
return v;
}
}
Идея состоит в том, чтобы использовать меньше кода, чем в предыдущем примере. Когда я писал что-то подобное на C++, я использовал std::bind
для создания константного массива ссылок на каждое задействованное поле, но я не знаю, как сделать что-то подобное на C#. Может ли кто-нибудь помочь мне с этим?
РЕДАКТИРОВАТЬ
Я нашел способ оптимизировать метод IncOrder
:
//...
private int _incDay() { return ++_orderDay; }
private int _incCustody() { return ++_orderCustody; }
private int _incBox() { return ++_orderBox; }
private IReadOnlyList<Func<int>> _funcs = Array.AsReadOnly(new Func<int>[] {_incDay, _incCustody, incBox});
public int IncOrder(int orderIndex) { return _funcs[orderIndex](); }
Может быть и другой способ, например, создать массив ссылок на эти поля, но я не знаю, возможно ли это.
Звучит как задание для перегрузки оператора индекса:
public int this[int index] => IncOrder(index);
Использование:
COrdering ordering = new COrdering();
int newValue = ordering[0];
Обновлено - вы можете использовать массив внутри
public class COrdering
{
public enum OrderIndex { Day = 0, Custody = 1, Box = 2, NumElements };
private readonly int[] values = new int[(int)OrderIndex.NumElements];
public int IncOrder(OrderIndex orderIndex) => ++values[(int)orderIndex];
public int this[OrderIndex index] => IncOrder(index);
}
Кроме того, ваш конструктор можно удалить, в C# все автоматически инициализируется до 0 (или нуля для ссылочных типов).
Это хорошая идея для внешнего доступа к этим закрытым членам и их увеличения. Но я очень хочу оптимизировать метод IncOrder
.
@delverdl Я добавил пример с массивом :)
Подумайте о том, чтобы придать смысл вашим индексам и использовать перечисление, код будет намного более читабельным и простым для понимания.
В приведенном выше примере кода опасайтесь жестко закодированного значения 3 и используйте последнее значение перечисления в качестве «общего количества», см. мой другой ответ ниже.
Почему бы не использовать Dictionary<int, int>
?
public class COrdering
{
Dictionary<int, int> map = new Dictionary<int, int>();
public COrdering() { map[0] = 0; map[1] = 0; map[2] = 0; }
public int IncOrder(int orderIndex)
{
return ++map[orderIndex];
}
}
На самом деле вы даже можете использовать int[]
или List<int>
.
Словарь не имеет смысла, если вы просто получаете значения, используя индекс.
Я понимаю, что вы хотите упростить свой код, поэтому в этом случае начните с переменных, в которых вы сохраняете данные, если вы обращаетесь к ним по индексу, было бы разумнее объявить массив и использовать перечисление, что-то вроде этого:
public class COrdering
{
enum OrderType
{
Day = 0,
Custody = 1,
Box = 2,
Count = 3
};
private int[] _order = new int[(int)OrderType.Count];
public int IncOrder(OrderType orderIndex)
{
// Increment corresponding order type and return its value
return ++_order[(int)orderIndex];
}
}
Вы можете видеть, что реализуете свой IncOrder всего одной строкой кода. ++ должен стоять перед именем переменной, чтобы вы получили правильный ответ. Я либо использую промежуточную переменную для приращения, либо ++ перед хорошим комментарием, чтобы следующий программист это увидел.
Другое решение с перегрузкой [] является неожиданным и удивительным для следующего парня, отлаживающего ваш код :-), так что, как говорится, я полагаю, вы догадываетесь, какой я выбрал.
ваше редактирование, вероятно, должно быть ответом.