Search code examples
c#databaseswitch-statementstreamreader

Switch statement that makes different child classes of one parent class does not work


hopefully this isnt too complicated, I am just wondering why this switch statement isnt working. Band is the parent class and the child classes are different types of bands (RockBand, JazzCombo, SoloAct, default). When I have the switch statement in place it catches and produces the error, only loading 2 bands. Is there anything wrong with the syntax?

class Bands
{
    private List<Band> bands = new List<Band>();
    private Dictionary<string, Band> bandsByName = new Dictionary<string, Band>();

    public Bands()
    {
        string fileName = @"C:\Users\Lkvideorang\Documents\Visual Studio 2013\Projects\KernRadio\KernRadio\bin\Debug\bands.txt";

        try
        {
            using (StreamReader myRdr = new StreamReader(fileName))
            {
                string line;
                while ((line = myRdr.ReadLine()) != null)
                {
                    string[] lineAra = line.Split('|');

                    switch (lineAra[1])
                    {
                        case "RockBand":
                            Band newBand = new RockBand(lineAra);
                            bands.Add(newBand);
                            bandsByName.Add(newBand.Name, newBand);
                            break;
                        case "JazzCombo":
                            Band newt = new JazzCombo(lineAra);
                            bands.Add(newt);
                            bandsByName.Add(newt.Name, newt);
                            break;
                        case "SoloAct":
                            Band newB = new SoloAct(lineAra);
                            bands.Add(newB);
                            bandsByName.Add(newB.Name, newB);
                            break;
                        default:
                            Band ddd = new Band(lineAra);
                            bands.Add(ddd);
                            bandsByName.Add(ddd.Name, ddd);
                            break;
                    }
                }
            }
            Console.WriteLine("loaded " + bands.Count + " bands");
        }
        catch
        {
            Console.WriteLine("Error reading file! Read " + bands.Count + " tunes.");
        }

    }

rockband class. This is where my main trouble is, my professor wants us to make the members of the band class Musician but I dont really understand how to utilize it and assign with that class. Ill post that class too.

class RockBand : Band
    {


       private Musician vocalist;
       private Musician bass;
       private Musician drums;
       private Musician guitar;


        public RockBand (string[] lineAra) : base (lineAra,)
        {
            vocalist.Name = lineAra[2];




        }
    }

Class Musician

class Musician
{
    string name;
    string instrument;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public string Instrument
    {
        get { return instrument; }
        set { instrument = value; }
    }

   public Musician(string [] lineAra)
    {
        name = lineAra[0];
        instrument = lineAra[1];
    }
}

The txt file looks like this

Al & GenJam|JazzCombo|GenJam|GenJam|GenJam|GenJam|Al Biles
John Coltrane Quartet|JazzCombo|McCoy Tyner|Jimmy Garrison|Elvin Jones|John Coltrane
Beatles|RockBand|John Lennon|Paul McCartney|Ringo Starr|George Harrison
Miles Davis Quintet|JazzCombo|Herbie Hancock|Ron Carter|Tony Williams|Miles Davis|Wayne Shorter
Michael Jackson|SoloAct
Weird Al|SoloAct
Polka Punks|PolkaBand
Herbie Hancock Trio|JazzCombo|Herbie Hancock|Ron Carter|Tony Williams

the dudes.txt

John Lennon|guitar
Paul McCartney|bass
Ringo Starr|drums
George Harrison|guitar
Al Biles|trumpet
GenJam|code
Michael Jackson|vocals
Weird Al|accordian
John Coltrane|sax
Miles Davis|trumpet
Wayne Shorter|sax
McCoy Tyner|piano
Jimmy Garrison|bass
Elvin Jones|drums
Tony Williams|drums
Herbie Hancock|piano
Ron Carter|bass

Also if there is a way to have newBand repeated in each case instead of me different variables for each that would be amazing. Thanks in advance!!


Solution

  • The reason you were getting the NullReferenceException is because you are trying to set the names of musicians before you have initialised the musician objects. What you want to do is this:

    public class RockBand : Band
    {
        private Musician vocalist;
        private Musician bass;
        private Musician drums;
        private Musician guitar;
    
        public RockBand (string[] lineAra) 
            : base(lineAra)
        {
            if (lineAra.Length >= 3)
                vocalist = new Musician(lineAra[2], "Vocals");
    
            if (lineAra.Length >= 4)
                bass = new Musician(lineAra[3], "bass");
    
            if (lineAra.Length >= 5)
                drums = new Musician(lineAra[4], "Drums");
    
            if (lineAra.Length >= 6)
                guitar = new Musician(lineAra[5], "Guitar");
        }
    } 
    

    You will have to add another constructor to Musician for this:

    public Musician(string name, string instrument)
    {
        this.Name = name;
        this.Instrument = instrument;
    }
    

    Notice I've also added a check to see if the element exists in the array before trying to access it. This is to avoid an IndexOutOfRangeException.

    You can also simplify the code for loading the file:

    public Bands()
    {
        string fileName = @"C:\Users\Lkvideorang\Documents\Visual Studio 2013\Projects\KernRadio\KernRadio\bin\Debug\bands.txt";
    
        string[] allLines;
    
        try
        {
            allLines = File.ReadAllLines(fileName);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error reading file! Exception: " + ex.Message);
            return;
        }
    
        bands = new List<Band>();
    
        foreach (var line in allLines)
        {
            try
            {
                string[] lineAra = line.Split('|');
    
                if (lineAra.Length < 2) continue;
    
                switch (lineAra[1])
                {
                    case "RockBand":
                        bands.Add(new RockBand(lineAra));
                        break;
                    case "JazzCombo":
                        bands.Add(new JazzCombo(lineAra));
                        break;
                    case "SoloAct":
                        bands.Add(new SoloAct(lineAra));
                        break;
                    default:
                        bands.Add(new Band(lineAra));
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error parsing line {0}. Exception: {1}", line, ex.Message);
            }
        }
    
        bandsByName = bands.ToList().ToDictionary(x => x.Name, x => x);
    
        Console.WriteLine("loaded " + bands.Count + " bands");
    }
    

    Here I've changed the stream reader to just File.ReadAllLines and used .ToDictionary() to create the lookup after all the bands have been loaded.

    I also added error handling for each line so that you will be able to see which line is causing the error if you have problems in future.

    If you have any problems understanding changes let me know.