开发者

Enumerations values set to different numbers / resetting enumeration values

I am trying to create a program that will calculate different musical scales based on the starting note that you provide.

I have an enumeration for the different notes:

public enum NoteValue
{
    A = 0,
    Asharp = 1,
    B = 2,
    C = 3,
    Csharp = 4,
    D = 5,
    Dsharp = 6,
    E = 7,
    F = 8,
    Fsharp = 9,
    G = 10,
    Gsharp = 11
}

I then have a method that sets each note

        public void setNotes(NoteValue startingNote)
        {
        //Creates an array of notes the size that is specified
        theNote = new Note[(numberOfNotes)];

        //Sets the notes
        theNote[0] = new Note(startingNote);
        theNote[1] = new Note((startingNote + step[1]));
        theNote[2] = new Note((startingNote + step[2] + step[1]));
        theNote[3] = new Note((startingNote + step[3] + step[2] + step[1]));
        theNote[4] = new Note((startingNote + step[4] + step[3] + step[2] + step[1]));
        theNote[5] = new Note((startingNote + step[5] + step[4] + step[3] + step[2] + step[1]));
        theNote[6] = new Note((startin开发者_高级运维gNote - step[7]));

        Console.WriteLine("{0} \n{1} \n{2} \n{3} \n{4} \n{5} \n{6}",
            theNote[0].value, theNote[1].value, theNote[2].value, theNote[3].value,
            theNote[4].value, theNote[5].value, theNote[6].value);
    }

The issue I'm having is that if it goes I start with G (which is 10 in my enumeration), it will just start printing numbers after G#. Can I make it so that it will return back to 0 after 11, rather than just keep going on?

I'll get something like this (for major scale):

G 12 14 15 17 19

instead of

G A B C D E F#

Is there any way to fix this? Thank you.


Enumerations as they are defined in C# are basically "strongly typed" wrappers for integral types (integers).

If you want this sort of wrapping behavior for integers, the common solution is to use the modulo (%) operator:

int note = 12;
var correctlyWrappedNote = note % 12; // will equal 0

This is logically equivalent to taking a remainder after dividing by 12.

You should then be able to cast it back to your NoteValue type:

var actualNote = (NoteValue)correctlyWrappedNote;

If you feed a negative number to modulo, though, you'll get a negative result. If you have to deal with negative numbers, then there's an extra step:

int note = -1;
var correctlyWrappedNote = note % 12; // will equal -1

if (correctlyWrappedNote < 0)
    correctlyWrappedNote = 12 + correctlyWrappedNote; // will equal 11

var actualNote = (NoteValue)correctlyWrappedNote; // Will equal Gsharp


@Merlyn's answer contains the gist of what you need to do, but using %12 just because your enum member's happen to be 12 and because each number 0 through 11 is assigned to one of the enum members is a recipe for broken code down the line. To make it more change resilient, you could write it like this

var notes = Enum.GetValues(typeof(NoteValue)); //array
var startingNote = Array.IndexOf(notes,NoteValue.Fsharp);//8
var fourNotesAfterStartingNote = notes[(startingNote+4)%notes.Length];//Asharp

The above code will continue to function correctly even if a new note is added. Unlikely maybe- but then again code always changes :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜