Indexers are unnamed. You use the this
keyword to create an
indexer:
public string this[int index]
Any type can be used, although it’s most common to use integers.
The elements of the array must implement IComparable
.
Generics allow you to create type-safe collections without specifying the type the collection will hold when you create the collection.
It allows your collection to support a foreach
loop.
The size of an array is fixed when you create it. A
List<T>
expands
dynamically when you add more elements.
A List is like an expandable array. A Stack is a “Last In, First Out” collection, a Queue is a “First In, First Out” collection, and a Dictionary is a collection of key/value pairs where you can retrieve the value given a key.
Create an abstract Animal
class that has private members
weight and name, and abstract methods Speak( )
, Move( )
, and ToString( )
. Derive from Animal
a Cat
and Dog
class that override the methods
appropriately. Create an Animal
array, populate it with
Dogs
and Cats
, and then call each member’s
overridden virtual method.
using System; abstract public class Animal { protected int weight; protected string name; public Animal(int weight, string name) { this.weight = weight; this.name = name; } abstract public void Speak( ); abstract public void Move( ); public override string ToString( ) { throw new Exception("The method or operation is not implemented."); } } public class Dog : Animal { private string breed; public string Breed { get { return breed; } set { breed = value; } } public Dog (int weight, string name, string breed): base(weight,name) { this.breed = breed; } public override void Speak( ) { Console.WriteLine ("Woof"); } public override void Move ( ) { Console.WriteLine ("Run, run, run, drool."); } public override string ToString( ) { return "My name is " + this.name + " I weigh " + this.weight + " and I am a " + this.breed + " "; } } public class Cat : Animal { public Cat (int weight, string name): base(weight,name) {} public override void Speak( ) { Console.WriteLine ("Meow"); } public override void Move ( ) { Console.WriteLine ("Run, tumble, nap."); } public override string ToString( ) { return "My name is " + this.name + " I weigh " + this.weight + " and I know how to purr! "; } public void Purr( ) { Console.WriteLine("Purrrrrrrrrrrrrrrrrrrrrrrrrr "); } } public class Tester { static void Main( ) { Animal[] myAnimals = new Animal[5]; myAnimals[0] = new Dog( 72, "Milo", "Golden" ); myAnimals[1] = new Cat( 12, "Shakespeare"); myAnimals[2] = new Cat( 10, "Allegra"); myAnimals[3] = new Dog( 50, "Dingo", "mixed breed" ); myAnimals[4] = new Dog( 20, "Brandy", "Beagle" ); foreach ( Animal a in myAnimals ) { a.Speak( ); a.Move( ); Console.WriteLine(a); Cat c = a as Cat; // cast to cat if ( c != null ) // if it is a cat { c.Purr( ); // only cats purr } } } }
Replace the array in Exercise 14-1 with a List
. Sort the animals by size. You
can simplify by just calling ToString( )
before and after the sort. Remember that you’ll need
to implement IComparable
.
using System; using System.Collections.Generic; abstract public class Animal : IComparable { protected int weight; protected string name; public Animal(int weight, string name) { this.weight = weight; this.name = name; } abstract public void Speak( ); abstract public void Move( ); public override string ToString( ) { throw new Exception("The method or operation is not implemented."); } public int CompareTo( Object rhs ) { Animal otherAnimal = rhs as Animal; if ( otherAnimal != null ) { return this.weight.CompareTo( otherAnimal.weight ); } else { throw new ApplicationException("Expected to compare animals"); } } } public class Dog : Animal { private string breed; public string Breed { get { return breed; } set { breed = value; } } public Dog (int weight, string name, string breed): base(weight,name) { this.breed = breed; } public override void Speak( ) { Console.WriteLine ("Woof"); } public override void Move ( ) { Console.WriteLine ("Run, run, run, drool."); } public override string ToString( ) { return "My name is " + this.name + " I weigh " + this.weight + " and I am a " + this.breed ; } } public class Cat : Animal { public Cat (int weight, string name): base(weight,name) {} public override void Speak( ) { Console.WriteLine ("Meow"); } public override void Move ( ) { Console.WriteLine ("Run, tumble, nap."); } public override string ToString( ) { return "My name is " + this.name + " I weigh " + this.weight + " and I know how to purr!"; } public void Purr( ) { Console.WriteLine("Purrrrrrrrrrrrrrrrrrrrrrrrrr "); } } public class Tester { static void Main( ) { List<Animal> myAnimals = new List<Animal>( ); myAnimals.Add(new Dog( 72, "Milo", "Golden" )); myAnimals.Add(new Cat( 12, "Shakespeare")); myAnimals.Add(new Cat( 10, "Allegra")); myAnimals.Add(new Dog( 50, "Dingo", "mixed breed" )); myAnimals.Add(new Dog( 20, "Brandy", "Beagle" )); foreach ( Animal a in myAnimals ) { Console.WriteLine(a); } Console.WriteLine( " After sorting by size..." ); myAnimals.Sort( ); foreach ( Animal a in myAnimals ) { Console.WriteLine( a ); } } }
Replace the list from Exercise 14-2 with both a Stack and a Queue, and see the difference in the order in which the animals are returned.
The animal definitions are unchanged; the Tester
class has the changes:
Using System.Collections.Generic; public class Tester { static void Main( ) { Console.WriteLine( "Adding in the order: Milo, Shakespeare, Allegra, Dingo, Brandy" ); Stack<Animal> myStackOfAnimals = new Stack<Animal>( ); myStackOfAnimals.Push( new Dog( 72, "Milo", "Golden" ) ); myStackOfAnimals.Push( new Cat( 12, "Shakespeare" ) ); myStackOfAnimals.Push( new Cat( 10, "Allegra" ) ); myStackOfAnimals.Push( new Dog( 50, "Dingo", "mixed breed" ) ); myStackOfAnimals.Push( new Dog( 20, "Brandy", "Beagle" ) ); Queue<Animal> myQueueOfAnimals = new Queue<Animal>( ); myQueueOfAnimals.Enqueue( new Dog( 72, "Milo", "Golden" ) ); myQueueOfAnimals.Enqueue( new Cat( 12, "Shakespeare" ) ); myQueueOfAnimals.Enqueue( new Cat( 10, "Allegra" ) ); myQueueOfAnimals.Enqueue( new Dog( 50, "Dingo", "mixed breed" ) ); myQueueOfAnimals.Enqueue( new Dog( 20, "Brandy", "Beagle" ) ); Console.WriteLine( "The stack..." ); foreach ( Animal a in myStackOfAnimals ) { Console.WriteLine(a); } Console.WriteLine( "The queue..." ); foreach ( Animal a in myQueueOfAnimals ) { Console.WriteLine( a ); } } }
Rewrite Exercise 14-2 to allow Animals
to be sorted either by weight
or alphabetically by name:
using System; using System.Collections.Generic; // simplified to show comparision abstract public class Animal : IComparable<Animal> { protected int weight; protected string name; public Animal( int weight, string name ) { this.weight = weight; this.name = name; } // ** new ** public static AnimalComparer GetComparer() { return new Animal.AnimalComparer(); } public int CompareTo( Animal rhs ) { return this.weight.CompareTo( rhs.weight ); } // ** new ** public int CompareTo( Animal rhs, Animal.AnimalComparer.ComparisonType whichComparison ) { switch ( whichComparison ) { case AnimalComparer.ComparisonType.name: return this.name.CompareTo( rhs.name ); case AnimalComparer.ComparisonType.size: return this.weight.CompareTo( rhs.weight ); } return -1; // gotta have all paths return a value } // nested class ** new ** public class AnimalComparer : IComparer<Animal> { // how do you want to compare? public enum ComparisonType { Size, Name }; private Animal.AnimalComparer.ComparisonType whichComparison; public Animal.AnimalComparer.ComparisonType WhichComparison { get { return whichComparison; } set { whichComparison = value; } } // compare two Animals using the previously set // whichComparison value public int Compare( Animal lhs, Animal rhs ) { return lhs.CompareTo( rhs, whichComparison ); } // required to fulfill implementation public bool Equals( Animal lhs, Animal rhs ) { return this.Compare( lhs, rhs ) == 0; } // required to fulfill implementation public int GetHashCode( Animal a ) { return a.weight.GetHashCode(); } } // end nested class } // end class Animal public class Dog : Animal { public Dog( int weight, string name, string breed ) : base( weight, name ) {} public override string ToString() { return "My name is " + this.name + " I weigh " + this.weight; } } public class Cat : Animal { public Cat( int weight, string name ) : base( weight, name ) { } public override string ToString() { return "My name is " + this.name + " I weigh " + this.weight; } } public class Tester { static void Main() { List<Animal> myAnimals = new List<Animal>(); myAnimals.Add( new Dog( 70, "Milo", "Golden" ) ); myAnimals.Add( new Cat( 10, "Shakespeare" ) ); myAnimals.Add( new Cat( 15, "Allegra" ) ); myAnimals.Add( new Dog( 50, "Dingo", "mixed breed" ) ); myAnimals.Add( new Dog( 20, "Brandy", "Beagle" ) ); Console.WriteLine( "Before sorting..." ); foreach ( Animal a in myAnimals ) { Console.WriteLine( a ); } Console.WriteLine( " After sorting by default (weight)..." ); myAnimals.Sort(); foreach ( Animal a in myAnimals ) { Console.WriteLine( a ); } Console.WriteLine( " After sorting by name..." ); Animal.AnimalComparer animalComparer = Animal.GetComparer(); animalComparer.WhichComparison = Animal.AnimalComparer.ComparisonType.name; myAnimals.Sort( animalComparer ); foreach ( Animal a in myAnimals ) { Console.WriteLine( a ); } Console.WriteLine( " After sorting explicitly by size..." ); animalComparer.WhichComparison = Animal.AnimalComparer.ComparisonType.size; myAnimals.Sort( animalComparer ); foreach ( Animal a in myAnimals ) { Console.WriteLine( a ); } } // end main } // end tester