C# Хотите знать, есть ли какой-либо тип enum, который повторяет свое значение только в пределе - PullRequest
1 голос
/ 25 марта 2020

Извините за мой глупый вопрос, я не программировал 7 лет и забыл почти все.

Я хотел бы создать систему, которая может express музыкальные ноты, например, я создал следующее enum,

public enum Notes { C = 0, D, E, F, G, A, B };
Notes N = Notes.C;

while (true)
{
    Console.WriteLine(N);
    N++;
}

В этом коде, когда нота N достигает Note.B, значение не go возвращается к C. Как я могу заставить значение go вернуться к заметке. C?

Ваш ответ мне очень поможет.

С уважением.

Ответы [ 2 ]

6 голосов
/ 25 марта 2020

Вы можете использовать оператор остатка %, чтобы обернуть свой номер обратно:

while (true)
{
    Console.WriteLine(N);
    N++;
    // you'd have to do some conversions here as N is not a numeric type
    N = (Notes)((int)N % 7);
}

Вы также можете заменить жестко закодированные маги c число 7 на

Enum.GetValues(typeof(Notes)).Length

РЕДАКТИРОВАТЬ:

Я только что понял, что вы ищете тип , который делает это обтекание поведения. Ну, обычный enum не может этого сделать. Вам нужно написать пользовательский struct, который по сути является оберткой для int. Просто чтобы дать вам представление о том, как это будет выглядеть:

struct Notes {
    private int intValue;
    private int IntValue {
        get => intValue;
        set {
            intValue = value % 7;
        }
    }

    private Notes(int intValue) {
        this.intValue = intValue;
    }

    public static Notes operator ++(Notes note) {
        Notes newNote = note;
        newNote.IntValue++;
        return newNote;
    }

    public static Notes operator --(Notes note) {
        Notes newNote = note;
        newNote.IntValue--;
        return newNote;
    }

    public static Notes C => new Notes(0);
    // all the other notes here...

    public override string ToString() => intValue switch {
        0 => "C",
        1 => "D",
        2 => "E",
        3 => "F",
        4 => "G",
        5 => "A",
        6 => "B",
        _ => intValue.ToString() // or throw an exception
    };
}
3 голосов
/ 25 марта 2020

Хороший ответ от Sweeper, но если вы хотите что-то более читабельное (ИМХО), вы можете сделать что-то вроде:

while (true)
{
    if (!Enum.IsDefined(typeof(Notes), note))
        note = Notes.C;
    Console.WriteLine(note);
    note++;
}
...