C# Help

Associate
Joined
26 Apr 2009
Posts
204
I am stuck on a problem where I am being required to use IComparable, but I'm not sure why, can anyone help me?

This is how the problem has been worded to me
You should then ensure that the animals in the displayed list are sorted by the name of the animal using the List Sort method

This is the code I have in the main program
namespace Animals
{
public partial class AnimalForm : Form
{
List<NamedAnimal> animals = new List<NamedAnimal> {new Dog("Doggy"), new Cat("Candy"), new Horse("Horsey"), new Duck("Ducky"), new Cow("Mooo Machine")};

animals.Sort();


public AnimalForm()
{
InitializeComponent();
}

private void AnimalForm_Load(object sender, EventArgs e)
{
for (int i = 0; i < animals.Count; i++)
{
listBoxAnimal.Items.Add(animals.Name);
}
}

private void listBoxAnimal_SelectedIndexChanged(object sender, EventArgs e)
{
// Get selected index
int selection = listBoxAnimal.SelectedIndex;
// Now update display with information from this object
NamedAnimal animal = animals[selection];
pictureBox.Image = animal.Picture;
labelSpecies.Text = animal.Species;
labelSound.Text = animal.Sound;
labelLegs.Text = animal.NumberOfLegs.ToString();
lblnotes.Text = animal.GetNotes();
}
}
}


and the NamedAnimal class
namespace Animals
{
class NamedAnimal : Animal, IComparable<NamedAnimal>
{
string _Name;

public NamedAnimal(string species,
string imageName,
string sound,
int numberOfLegs)
: base(species, imageName, sound, numberOfLegs)
{
_Name = "Unnamed " + species;
}

public NamedAnimal(string name,
string species,
string imageName,
string sound,
int numberOfLegs)
: base(species, imageName, sound, numberOfLegs)
{
_Name = name;
}

public string Name
{
get
{
return _Name;
}
}

public virtual string GetNotes()
{
return "No notes avaliable";


}

public int CompareTo(NamedAnimal otherAnimal)
{
return _Name.CompareTo(otherAnimal.Name);
}


}
}
 
It uses CompareTo from IComparable to compare two items and determine which should come first. Otherwise how would it know how you wanted the items sorted?

Sorry, what I mean is I understand the concept, but the code doesn't work, and I'm not sure why the code doesn't work
 
try moving animals.Sort(); into AnimalForm_Load

failing that, elaborate on "doesn't work"

Thank you for that, it now doesn't produce a red line error. However, this may seem like a stupid question but it should now sort the animal names into alphabetical order?
 
Sort() is a void, it just sorts the generic list into the order specified by the implementation of CompareTo

It should sort the list and add it, in order, to the listBox.

Oh, and some syntax language usage, as that for() loop is making me itch:

foreach(var animal in animals)
{
listBoxAnimal.Items.Add(animal.Name);
}

:)
 
Dunno - just winging it without actually running your code :)

I think maybe Sort returns a result, and you're meant to use that result to bind your list?

Thank you for your help I do appreciate it, and understand the limitations of only having part of it.

Sort() is a void, it just sorts the generic list into the order specified by the implementation of CompareTo

It should sort the list and add it, in order, to the listBox.

Oh, and some syntax language usage, as that for() loop is making me itch:



:)

I didn't write the forloop but will make the changes :) I don't however, fully understand what you mean. As when I run the program the animals are not sorted into alphabetical order :S :(

Thank you for the help though its muchly appreciated
 
this works

Code:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            List<Whatever> whatevers = new List<Whatever>();
            whatevers.Add(new Whatever("b"));
            whatevers.Add(new Whatever("a"));
            whatevers.Add(new Whatever("c"));

            whatevers.Sort();

            foreach (Whatever whatever in whatevers)
            {
                this.listBox1.Items.Add(whatever.Name);
            }
        }
    }

    class Whatever : IComparable<Whatever>
    {
        public Whatever(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }

        public int CompareTo(Whatever other)
        {
            return Name.CompareTo(other.Name);
        }
    }
 
this works

Code:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            List<Whatever> whatevers = new List<Whatever>();
            whatevers.Add(new Whatever("b"));
            whatevers.Add(new Whatever("a"));
            whatevers.Add(new Whatever("c"));

            whatevers.Sort();

            foreach (Whatever whatever in whatevers)
            {
                this.listBox1.Items.Add(whatever.Name);
            }
        }
    }

    class Whatever : IComparable<Whatever>
    {
        public Whatever(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }

        public int CompareTo(Whatever other)
        {
            return Name.CompareTo(other.Name);
        }
    }

Thanks for that, it appears my code was right, it was simply I was adding them to the list box and then sorting them, without updating the list box. Amateurish really :(
 
Oh, and some syntax language usage, as that for() loop is making me itch:



:)

Could you expand on this? I am currently teaching myself C# (it's early days) and the book I am working through used the same for loop syntax as used by OP. Why do you suggest a foreach loop instead? I can accept that it is probably easier to understand, but is there anything inherently wrong with the for loop used by the OP? Is it bad practice? Is it inefficient?

Sorry to hijack the thread, it's just I'm interested in how developers decide on the best way to do something if there are multiple ways of achieving the same goal.
 
Unless you need to only loop between x and y items inside an array then foreach is just easier and you instantly know that you're working with everything inside the collection.

For is quicker than foreach (although it's probably negligible unless you have a lot of data) but you need to ensure your loop is set-up right - for (var i=0; i<animals.count-1; i++ would miss off the last item and it's not always obvious to spot, same goes with < vs <= for the test condition, I've spent ages not realising this in the past I'm sure :p and you also risk easily overwriting the counter variable somewhere in your loop if you think it's something else and potentially missing objects out.
 
Thanks Pho - that does help. So basically you would use the method that is easiest to code and the most readable in order to reduce the chances of error unless performance was an issue and then you would use the most efficient method.
 
Yep exactly. If you're debugging thousands of lines of code finding a dodgy for isn't always that easy and chances are you won't need to use for.

I'm actually debugging some old code right now which has to use for loops and extracts items from a hierarchy of ArrayLists containing ArrayLists (there are better choices than ArrayLists for this but as I say it's old and works).

PHP:
for (int i = 0; i < alItems.Count; i++)
{
	Item item = ((Item)((ArrayList)((ArrayList)alItems[i])[0])[0]);

	for (int j = ((ArrayList)alItems[i]).Count - 1; j >= 0; j--)
	{
		for (int k = 0; k < ((ArrayList)((ArrayList)alItems[i])[j]).Count; k++, ++children)
		{
			// ...
		}
		
		// ...
	}
	
	// ...
}

Not exactly easy to understand at first glance :p.
 
Thanks Pho - that does help. So basically you would use the method that is easiest to code and the most readable in order to reduce the chances of error unless performance was an issue and then you would use the most efficient method.

Developers spend far more time reading code than they do writing code, so write your code in a way that makes it easy to read and understand at a later date.

That's another benefit of doing it the LINQ way that Dj_Jestar suggested. It's easy to see exactly what you are trying to do by reading that bit of code.
 
Back
Top Bottom