Ссылка на несколько членов класса

Я хочу получить доступ к трем членам класса (_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](); }

Может быть и другой способ, например, создать массив ссылок на эти поля, но я не знаю, возможно ли это.

ваше редактирование, вероятно, должно быть ответом.

MakePeaceGreatAgain 21.12.2020 18:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
78
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Звучит как задание для перегрузки оператора индекса:

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 21.12.2020 17:10

@delverdl Я добавил пример с массивом :)

jjxtra 21.12.2020 17:28

Подумайте о том, чтобы придать смысл вашим индексам и использовать перечисление, код будет намного более читабельным и простым для понимания.

Pedro Ferreira 21.12.2020 17:49

В приведенном выше примере кода опасайтесь жестко закодированного значения 3 и используйте последнее значение перечисления в качестве «общего количества», см. мой другой ответ ниже.

Pedro Ferreira 23.12.2020 10:51

Почему бы не использовать 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>.

Словарь не имеет смысла, если вы просто получаете значения, используя индекс.

Pedro Ferreira 23.12.2020 10:57

Я понимаю, что вы хотите упростить свой код, поэтому в этом случае начните с переменных, в которых вы сохраняете данные, если вы обращаетесь к ним по индексу, было бы разумнее объявить массив и использовать перечисление, что-то вроде этого:

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 всего одной строкой кода. ++ должен стоять перед именем переменной, чтобы вы получили правильный ответ. Я либо использую промежуточную переменную для приращения, либо ++ перед хорошим комментарием, чтобы следующий программист это увидел.
Другое решение с перегрузкой [] является неожиданным и удивительным для следующего парня, отлаживающего ваш код :-), так что, как говорится, я полагаю, вы догадываетесь, какой я выбрал.

Другие вопросы по теме