C# Help!

Associate
Joined
22 May 2011
Posts
1,445
Location
Edinburgh
Hey all,

I'm having trouble with a piece of C#. I have code which as far as I am aware works correctly in distinguishing whether an object is of the base class, or one of its two child classes. However in another part of the program the conditions of class are never being met.. I have this:

Code:
foreach (Booking c in myCamp.camp)
            {
                string line = "Booking: " + c.week+" " + c.name + " " + c.address + " " + c.children;
                if (c.GetType() == typeof(Activity))
                    {
                        Activity a = (Activity)c;
                        line = line + a.kind + "dave " + a.U16;
                    }

                if (c.GetType() == typeof(Cruise))
                {
                    Cruise b = (Cruise)c;
                    line = line + b.bora;
                }
                lstBookings.Items.Add(line);
            }

Thing is neither of the ifs are ever satisfied and all instansiations come out as objects of the base class. Help!
 
To be perfectly honest you really shouldn't have to check the runtime type of a class very often at all.

Not sure what level of programmer you are, but it would be worth reading up on polymorphism as that would be a more preferable way of doing what you need to do here.
The type of booking would determine what the line is for itself, rather than having to check the type and do type casts all over the place.
 
Code:
using System;
using System.Collections.Generic;

namespace Lunawolfy
{
    public class Booking
    {
        public int week { get; set; }
        public string name { get; set; }
        public string address { get; set; }
        public int children { get; set; }

        public virtual string GetLine()
        {
            return string.Format("Booking: {0} {1} {2} {3}", week, name, address, children);
        }
    }

    public class Activity : Booking
    {
        public string kind { get; set; }
        public int U16 { get; set; }

        public override string GetLine()
        {
            return string.Format("{0} {1} {2}", base.GetLine(), kind, U16);
        }
    }

    public class Cruise : Booking
    {
        public string bora { get; set; }

        public override string GetLine()
        {
            return string.Format("{0} {1}", base.GetLine(), bora);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Test data
            var bookingData = new List<Booking>
            {
                new Booking{ week = 1, name="booking", address = "address 1", children = 1 },
                new Activity{ week = 2, name="activity", address = "address 2", children = 2, kind = "fun stuff", U16 = 2},
                new Cruise{ week = 3, name="cruise", address = "address 3", children = 3, bora = "bora bora"},
            };

            // Let the magic happen
            var bookings = new List<string>();
            foreach (var booking in bookingData)
            {
                var line = booking.GetLine();
                bookings.Add(line);
            }
        }
    }
}

This is what Haircut means (though no doubt someone will tell me I've done it wrong :p). No casts needed and will make life a lot easier.

base.GetLine() calls the GetLine() function of Booking and then appends extra stuff to it - you could write entirely different GetLine() outputs for each class and not use the base one if you wanted.
 
This is what Haircut means (though no doubt someone will tell me I've done it wrong :p). No casts needed and will make life a lot easier.

Yup, that's pretty much the sort of thing I meant.

Makes things much more flexible if other types of booking are introduced in the future as well.
 
I've added the code as posted above and it runs as it should, however it still is doing the same thing. I think the conditions on my IF statement are never being met :(

Code:
            if (theBooking == null) //If new bookingr...
            {
                if (ActivityButton.Checked == true)
                {
                    theBooking = new Activity(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text), label6.Text, comboBox1.Text,Convert.ToBoolean(comboBox3.SelectedItem));
                }

                if (CruiseButton.Checked == true)
                {
                    theBooking = new Cruise(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text), label7.Text, comboBox2.Text);
                }

                theBooking = new Booking(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text),label8.Text);

            }
            else
            {   //if editing an existing booking
                theBooking.name = txtName.Text;
                theBooking.week = txtWeek.Text;
                theBooking.address = txtAddress.Text;
                theBooking.children = Convert.ToInt32(txtChildren.Text);
                
            }
 
You're reassigning the value of theBooking after doing the if check (highlighted in bold).

Code:
if (ActivityButton.Checked == true)
{
   theBooking = ...;
}

if (CruiseButton.Checked == true)
{
   theBooking = ...;
}

[b]theBooking = new Booking(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text),label8.Text);[/b]

EDIT: Are you trying to do a nested if...else if...else statement?

Code:
if (ActivityButton.Checked)
{
   theBooking = new Activity(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text), label6.Text, comboBox1.Text,Convert.ToBoolean(comboBox3.SelectedItem));
}
[b]else if (CruiseButton.Checked)[/b]
{
   theBooking = new Cruise(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text), label7.Text, comboBox2.Text);
}
[b]else[/b]
{
   theBooking = new Booking(txtWeek.Text, txtName.Text, txtAddress.Text, Convert.ToInt32(txtChildren.Text),label8.Text);
}
 
Last edited:
You know you could have saved yourself all that hair pulling by proper use of the debugger.
I assume you're using Visual Studio given that you're using C# and being able to debug properly is as important as being able to code IMO.

Have a look at the stuff here for some Visual Studio debugging tips:
http://www.codeproject.com/KB/cs/MasteringInDebugging.aspx

Stepping over the code and seeing that it was creating a Booking instance in all cases would have pinpointed the place in the code that was going wrong straight away.
 
If you'd written a unit test you'd have found it before you'd have needed to fire up the debugger.

/controversial

:)
 
Heh, I did think about mentioning unit tests, but thought that might be a little too much in one go seeing as he's a beginner!
 
I've been ploughing on and I've hit a snag, a Null Handling Exception.

Basically I have to add a Customer class, it doesn't need to link to anything, but it needs its own box to store the data in, very much a mirror copy of the stuff I already have, but when I run the method for updating the list it throws the above mentioned error :@

This is the class:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SD2coursework
{
    public class Customer
    {
        private string theName;
        private string theAddress;
        private int theID;

        public Customer(string aName, string anAddress, int anID)
        {
            theName = aName;
            theAddress = anAddress;
            theID = anID;
        }
    

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

    public string Address
    {
      get 
      {
          return theAddress;  
      }
      set 
      {
          theAddress = value;
      }
    }

    public int ID
    {
        get 
        {
          return theID;
        }
        set 
        {
          theID = value;
        }
    }

    public virtual string GetLine()
    {
        return string.Format("Name: {0}, Address: {1}, ID Number: {2} ", Name, Address, ID);
    }
    
    }
}

This is the customer storing method:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SD2coursework
{
    public partial class FrmCustBooking : Form
    {

        private Customer theCust = null;

        public Customer Cust
        {
            get 
            {
                return theCust;
            }

            set 
            {
                theCust = value;
                textBox1.Text = theCust.Name;
                textBox2.Text = theCust.Address;
                textBox3.Text = Convert.ToString(theCust.ID);
            }
        
        }


        public FrmCustBooking()
        {
            InitializeComponent();
        }

       
        private void button1_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    
        private void FrmCustBooking_FormClosed(object sender, FormClosedEventArgs e)
        {
            if(theCust == null)
            {
                theCust = new Customer(textBox1.Text, textBox2.Text, Convert.ToInt32(textBox3.Text));
            }

            else
            {
                theCust.Name = textBox1.Text;
                theCust.Address = textBox2.Text;
                theCust.ID = Convert.ToInt32(textBox3.Text);
            }
        }
    
    
    
    
    }
}

And the list update part

Code:
        private void updateBookingList()
        {   //Used to update the camp displayed on the form
            lstBookings.Items.Clear();
            foreach (var Booking in myCamp.camp)
            {
                var line = Booking.GetLine();
                lstBookings.Items.Add(line);
            }

            lstCustomers.Items.Clear();
            foreach (var Customer in cust.log)
            {
                var line = Customer.GetLine();
                lstCustomers.Items.Add(line);
            }
        }

Anyone see whats wrong? :'(
 
Leaving aside the hideous object model...what line is throwing the error?

There's a few places where there could be a null exception.
 
Either "Customer" is null, which is unlikely as it's a member of an enumeration, which can't be null, or one of the internal properties you are using to construct the external property (Name, Address, ID) is null.

in lieu of any unit tests, stick a breakpoint on this line:

return string.Format("Name: {0}, Address: {1}, ID Number: {2} ", Name, Address, ID);

...and inspect each of the values. Then work out why they haven't been set.
 
The getter for Customer Cust is trying to return a null object:
Code:
        ...
        private Customer theCust = null;

        public Customer Cust
        {
            get 
            {
                return theCust;
            }
        ...
        }
You could add a if(theCust== null) check and instantiate it just before returning theCust?
 
Last edited:
Back
Top Bottom