Home

Introduction to Collections

 

Overview of Collections

 

Introduction

A database is collection of values. To create these values, you can use a collection class. Fortunately, instead of creating a class from scratch, the .NET Framework provides a very impressive library of interfaces and collection classes. The built-in interfaces of the .NET Framework lay a foundation that other classes use to implement and customize the desired functionality. The various built-in collection classes are meant to satisfy various purposes. Some classes are available to any application and can be used by any Windows control. Some other collection classes are nested in classes that particularly need them.

The .NET Framework supports collections in various namespaces. While the System.Collections namespace provides regular collection classes, the System.Collections.Generic namespace contains the equivalent generic classes. 

Accessories for Collections

One the most routines operations performed on a database consists of reviewing its values. To assist you with this, the .NET Framework provides the IEnumerator and the IEnumerable interfaces that are defined in the System.Collections namespace. Their generic equivalences can be found in the System.Collections.Generic namespace. After implementing these interfaces, you can use the foreach operator to visit each value of the database.

To implement the System.Collections.IEnumerator interface, you must derive a class from it. Then, you must define the Reset(), the MoveNext() methods, and the Current property. Here is an example:

using System;
using System.Collections;

namespace Exercise
{
    public class Enumerator : IEnumerator 
    {
        private string[] names;
        private int cur;

        public Enumerator(string[] list)
        {
            this.names = list;
            cur = -1;
        }

        public Object Current
        {
            get { return names[cur]; }
        }

        public void Reset()
        {
            cur = -1;
        }

        public bool MoveNext()
        {
            cur++;

            if (cur < names.Length)
                return true;
            else
                return false;
        }
    }
}

To implement the System.Collections.IEnumerable interface, you must derive a class from it. When implementing the class, you must define an accessory method and the GetEnumerator() method that returns an IEnumerator object. Here is an example: 

using System;
using System.Collections;

namespace Exercise
{
    class Enumerable : IEnumerable
    {
        private string[] names;

        public void Identify(string[] values)
        {
            names = values;
            for (int i = 0; i < values.Length; i++)
                names[i] = values[i];
        }

        public IEnumerator GetEnumerator()
        {
            return new Enumerator(names);
        }
    }
}

Once you have implemented the interfaces, you can use foreach. Here is an example:

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 Exercise
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var FullNames = new string[8];

            FullNames[0] = "Gertrude Monay";
            FullNames[1] = "Paul Bertrand Yamaguchi";
            FullNames[2] = "Hermine Ngaleu";
            FullNames[3] = "Francine Mukoko";
            FullNames[4] = "Joseph Walters";
            FullNames[5] = "Patricia Katts";
            FullNames[6] = "Helen Cranston";
            FullNames[7] = "Paul Motto";

            var coll = new Enumerable();

            coll.Identify(FullNames);
            foreach (string s in coll)
                lbxNames.Items.Add(s);
        }
    }
}

IEnumerator, IEnumerable, and foreach

Choosing an Interface

While the IEnumerator and the IEnumerable interfaces serve as valuable accessories that allow a collection class to support enumeration, to actually create a collection class, there are other interfaces you can use to implement the functionality you want for your collection.

When you want to use a collection in your application, you may first check what classes are available in the .NET Framework. If you don't find a suitable class, you can create your own that implements one or more interfaces. As it happens, the .NET Framework ships with many of them and your next step is to choose which one you prefer. Some of the most commonly used interfaces are

The ICollection Interface

 

Introduction

One of the primary pieces of information you should provide about a the values in a database is the number of values that a list is (currently) holding. When creating a collection class, to prepare it to provide this valuable information, you can (should) implement an interface named ICollection. The ICollection interface is defined in the System.Collections namespace while its equivalent of the same name is defined in the System.Collections.Generic namespace. This means that, if you are creating a class that implements it, you should include this namespace in the file. Here is an example for the System.Collections.ICollection interface:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
    }
}

Implementing ICollection

To assist you with keeping track of the number of items in a collection, the ICollection interface is equipped with a property named Count, which you must implement. To do this, you can create a private member variable that will actually keep a count of the number of items. The Count property can then be used to communicate this information to the clients of the class. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
        private int NumberOfBooks;

        public Collection()
        {
            NumberOfBooks = 0;
        }

        public virtual int Count
        {
            get { return NumberOfBooks; }
        }
    }
}

The ICollection interface also allows its implementer to copy some of its items to an array. To provide this functionality, the interface is equipped with a method named CopyTo, which you must implement. The syntax of this method is:

void CopyTo(Array array, int index);

This method takes two arguments. The first argument is the array that will receive the items. The second argument is the index of the item from where the copying operation will begin. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
        . . . No Change

        public virtual void CopyTo(Array items, int index)
        {
            string[] bks = new string[Count];

            for (int i = 0; i < Count; i++)
                bks[i] = books[i];
            items = bks;
        }
    }
}

If you create a collection class, you can provide the ability to enumerate its items. When this is done, some time to time, you will want to identify or to know what item is currently being accessed. In case other collection classes are using the same function at the time you are accessing this information, you should have an object that is responsible for synchronizing the collection. To do this in your ICollection-based class, you must implement a property named SyncRoot. This property must return an Object object. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
        . . . No Change

        public virtual object SyncRoot
        {
            get { return this; }
        }
    }
}

Besides the ability to specify the number of items in a collection, a class that implements the ICollection interface must retrieve a value that indicates whether its item is synchronized. To give this information, you must implement a Boolean property named IsSynchronized. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
        . . . No Change

        public virtual bool IsSynchronized
        {
            get { return false; }
        }
    }
}

System.Collections.ICollection (and System.Collections.Generic.ICollection) exdepends the IEnumerable interface. This means that you should be able to use foreach in your ICollection-based class but you must create the functionality yourself, which is done by implementing the GetEnumerator() method. Even if you don't want to support this feature, you still must provide at least a skeleton for this method. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class Collection : ICollection
    {
        private int NumberOfBooks;
        private string[] books;

        public Collection()
        {
            NumberOfBooks = 0;
            books = new string[5];
        }

        public virtual int Count
        {
            get { return NumberOfBooks; }
        }

        public virtual void CopyTo(Array items, int index)
        {
            string[] bks = new string[Count];

            for (int i = 0; i < Count; i++)
                bks[i] = books[i];
            items = bks;
        }

        public virtual object SyncRoot
        {
            get { return this; }
        }

        public virtual bool IsSynchronized
        {
            get { return false; }
        }

        public IEnumerator GetEnumerator()
        {
            return null;
        }
    }
}

The IList Interface

 

Introduction

While it provides the minimum functionality of a collection, the System.Collections.ICollection (and the System.Collections.Generic.ICollection) interface is not equipped to perform the regular operations of a collection class, such as adding, retrieving, or deleting items from a set.

To assist you with creating a collection class as complete as possible, the .NET Framework provides an interface named IList. The IList interface is defined in the System.Collections namespace and its equivalent of the same name is defined in the System.Collections.Generic namespace. The interface is equipped with the methods necessary to add, insert, delete, or retrieve items from a collection. Because the functionalities of these methods may not suit you, to use these features, you must create a class that implements them.

Practical Learning Practical Learning: Starting a Custom Collection Class

  1. Start Microsoft Visual C# and create a new Windows Application named MusicalInstrumentStore2
  2. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  3. Set the name to CategoryEditor and click Add
  4. Design the form as follows:
     
    Control Text Name Other Properties
    Label &Category:    
    TextBox   txtCategory Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Category Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  5. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  6. Set the name to TypeEditor and click Add
  7. Design the form as follows:
     
    Musical Store Item Type
    Control Text Name Other Properties
    Label &Item Type:    
    TextBox   txtItemType Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Type Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  8. To create a dialog box, in the Solution Explorer, right-click MusicalInstrumentStore2 -> Add -> Windows Form...
  9. Set the name to ItemEditor and click Add
  10. Design the form as follows:
     
    Musical Store Item
     
    Control Text Name Other Properties
    Label &Item #:    
    TextBox   txtItemNumber  
    Label &Category:    
    ComboBox   cbxCategories  
    Button New C&ategory... btnNewCategory  
    Label &Item Type:    
    ComboBox   cbxItemTypes  
    Button New &Item Type... btnNewItemType  
    Label Item &Name:    
    TextBox   txtItemName  
    Label &Unit Price:    
    TextBox 0.00 txtUnitPrice TextAlign: Right
    Button Picture... btnPicture  
    TextBox   txtPicturePath  
    PictureBox   pbxPicturePath SizeMode: Zoom
    Button Create btnCreate  
    Button Close btnClose DialogResult: Cancel
    OpenFileDialog (Name): dlgOpen
    Title: Select Item Picture
    DefaultExt: jpg
    Filter: JPEG Files (*.jpg,*.jpeg)|*.jpg|GIF Files (*.gif)|*.gif|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png
    Form Property Value
    FormBorderStyle FixedDialog
    Text Musical Instrument Store - Item Editor
    StartPosition CenterScreen
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  11. Double-click the New Category button and implement it as follows:
      
    private void btnNewCategory_Click(object sender, EventArgs e)
    {
        var editor = new CategoryEditor();
    
        if (editor.ShowDialog() == DialogResult.OK)
        {
            if (editor.txtCategory.Text.Length > 0)
            {
                var NewCategory = editor.txtCategory.Text;
    
                // Make sure the category is not yet in the list
                if (cbxCategories.Items.Contains(NewCategory))
                    MessageBox.Show(NewCategory + " is already in the list");
                else
                {
                    // Since this is a new category, add it to the combox box
                    cbxCategories.Items.Add(NewCategory);
                    // Just in case the user wanted to use this new category
                    // select it
                    cbxCategories.Text = NewCategory;
                }
            }
        }
    }
  12. Return to the Item Editor dialog box and double-click the New Item Type button
  13. Implement the event as follows:
      
    private void btnNewItemType_Click(object sender, EventArgs e)
    {
        var editor = new TypeEditor();
    
        if (editor.ShowDialog() == DialogResult.OK)
        {
            if (editor.txtItemType.Text.Length > 0)
            {
                string NewType = editor.txtItemType.Text;
    
                // Make sure the type is not yet in the list
                if (cbxTypes.Items.Contains(NewType))
                    MessageBox.Show("The list already contains " +
                                    NewType);
                else
                {
                    cbxTypes.Items.Add(NewType);
                    cbxTypes.Text = NewType;
                 }
            }
        }
    }
  14. Return to the Item Editor dialog box and double-click the Picture button
  15. Implement the event as follows:
      
    private void btnPicture_Click(object sender, EventArgs e)
    {
        if (dlgPicture.ShowDialog() == DialogResult.OK)
        {
            txtPicturePath.Text = dlgPicture.FileName;
            pbxStoreItem.Image = Image.FromFile(txtPicturePath.Text);
        }
    }
  16. In the Solution Explorer, right-click Form1.cs and click Rename
  17. Type MusicStore.cs and press Enter twice (to display the form)
  18. Design the form as follows:
     
    Musical Instrument Store
     
    Control Text Name Other Properties
    Label Label Item Category:    
    ComboBox ComboBox   cbxCategories  
    Label Label Items Type:    
    ComboBox ComboBox   cbxTypes  
    Label Label Available Items    
    Button Button New Store Item... btnNewStoreItem  
    ListView ListView   lvwStoreItems View: Details
    FullRowSelect: True
    GridLines: True
    Columns
    (Name) Text TextAlign Width
    colItemNumber Item #    
    colItemName Item Name/Description   320
    colUnitPrice Unit Price Right  
    PictureBox   pbxStoreItem SizeMode: Zoom
    GroupBox GroupBox Selected Items    
    Label Label Item #    
    Label Label Description    
    Label Label Unit Price    
    Label Label Qty    
    Label Label Sub Total    
    TextBox TextBox   txtItemNumber1  
    TextBox TextBox   txtDescription1  
    TextBox TextBox 0.00 txtUnitPrice1 TextAlign: Right
    TextBox TextBox 0 txtQuantity1 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal1 TextAlign: Right
    Button Button Remove btnRemove1  
    TextBox TextBox   txtItemNumber2  
    TextBox TextBox   txtDescription2  
    TextBox TextBox 0.00 txtUnitPrice2 TextAlign: Right
    TextBox TextBox 0 txtQuantity2 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal2 TextAlign: Right
    Button Button Remove btnRemove2  
    TextBox TextBox   txtItemNumber3  
    TextBox TextBox   txtDescription3  
    TextBox TextBox 0.00 txtUnitPrice3 TextAlign: Right
    TextBox TextBox 0 txtQuantity3 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal3 TextAlign: Right
    Button Button Remove btnRemove3  
    TextBox TextBox   txtItemNumber4  
    TextBox TextBox   txtDescription4  
    TextBox TextBox 0.00 txtUnitPrice4 TextAlign: Right
    TextBox TextBox 0 txtQuantity4 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal4 TextAlign: Right
    Button Button Remove btnRemove4  
    TextBox TextBox   txtItemNumber5  
    TextBox TextBox   txtDescription5  
    TextBox TextBox 0.00 txtUnitPrice5 TextAlign: Right
    TextBox TextBox 0 txtQuantity5 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal5 TextAlign: Right
    Button Button Remove btnRemove5  
    TextBox TextBox   txtItemNumber6  
    TextBox TextBox   txtDescription6  
    TextBox TextBox 0.00 txtUnitPrice6 TextAlign: Right
    TextBox TextBox 0 txtQuantity6 TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal6 TextAlign: Right
    Button Button Remove btnRemove6  
    GroupBox GroupBox Order Summary    
    Label Label Items Total:    
    TextBox TextBox 0.00 txtItemsTotal TextAlign: Right
    Label Label Tax Rate:    
    TextBox TextBox 7.75   TextAlign: Right
    Label Label %    
    Label Label Tax Amount:    
    TextBox TextBox 0.00 txtTaxAmount TextAlign: Right
    Label Label Order Total:    
    TextBox TextBox 0.00 txtOrderTotal TextAlign: Right
    Button Button Save btnSave  
    Label Label Receipt #:    
    TextBox TextBox 0.00 txtReceiptNumber  
    Button Button &Open btnOpen  
    Button Button New Order btnNewOrder  
    Button Button Close btnClose  
  19. To create a new class, in the Solution Explorer, right-click MusicalInstrumentStore2 -> Add -> Class...
  20. Set the Name to StoreItem and press Enter
  21. Change the file as follows:
      
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MusicalInstrumentStore2
    {
        [Serializable]
        public class StoreItem
        {
            private string nbr;
            private string cat;
            private string tp;
            private string nm;
            private double prc;
    
            public string ItemNumber
            {
                get { return nbr; }
                set { nbr = value; }
            }
    
            public string Category
            {
                get { return cat; }
                set { cat = value; }
            }
    
            public string Type
            {
                get { return tp; }
                set { tp = value; }
            }
    
            public string ItemName
            {
                get { return nm; }
                set { nm = value; }
            }
    
            public double UnitPrice
            {
                get { return prc; }
                set { prc = value; }
            }
    
            public virtual bool Equals(StoreItem same)
            {
                if( (nbr == same.nbr) &&
                    (cat == same.cat) &&
                    (tp  == same.tp) &&
                    (nm  == same.nm) &&
                    (prc == same.prc))
                    return true;
                else
                    return false;
            }
    
            public StoreItem()
            {
                nbr = "000000";
                cat = "Accessories";
                tp  = "Accessories";
                nm  = "Unknown";
                prc = 0.00;
            }
    
            public StoreItem(string itmNumber)
            {
                nbr = itmNumber;
                cat = "Accessories";
                tp  = "Accessories";
                nm  = "Unknown";
                prc = 0.00;
            }
    
            public StoreItem(string itmNumber, string category,
                      string type, string name, double price)
            {
                nbr = itmNumber;
                cat = category;
                tp  = type;
                nm  = name;
                prc = price;
            }
        }
    }
  22. Save the file

Implementing IList

As mentioned above, to create a collection, you can derive it from the IList interface. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
    }
}

This System.Collections.IList interface is declared as follows:

public interface IList : ICollection, IEnumerable

This System.Collections.Generic.IList interface is declared as follows:

public interface IList<T> : ICollection<T>,
			    IEnumerable<T>, 
			    IEnumerable

This means that the IList interface exdends both the ICollection and the IEnumerable interfaces. This also implies that you must implement the members of these parent interfaces. In other words, you must implement the Count property, the SyncRoot property, the IsSynchronized property, and the CopyTo() method of the ICollection interface. From what we learned with ICollection, here are examples of implementing these members for the System.Collections.IList interface:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        private int counter;
        private object[] objs;

        public BookList()
        {
            counter = 0;
            objs = new array[5];
        }

        public virtual int Count
        {
            get { return items; }
        }

        public virtual bool IsSynchronized
        {
            get { return false; }
        }

        public virtual object SyncRoot
        {
            get { return this; }
        }

        public virtual void CopyTo(Array ary, int index)
        {
        }
    }
}

You must also implement the System.Collections.GetEnumerator() (or the System.Collections.Generic.GetEnumerator()) method of the System.Collections.IEnumerable  (or of the System.Collections.Generic.IEnumerable) interface. If you do not have time to completely implement it, you can simply return null. Here is an example for the System.Collections.IList interface:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public IEnumerator GetEnumerator()
        {
            return null;
        }
    }
}

Practical Learning Practical Learning: Implementing the IList Interface

  1. To create a new class, in the Class View, right-click MusicalInstrumentStore2 -> Add -> Class...
  2. Set the Name to StoreItems and press Enter
  3. Change the file as follows:
      
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    
    namespace MusicalInstrumentStore2
    {
        [Serializable]
        public class StoreItems : IList
        {
            int counter;
            private object[] items;
    
            public virtual int Count
            {
                get { return counter; }
            }
    
            public virtual bool IsSynchronized
            {
                get { return false; }
            }
    
            public virtual object SyncRoot
            {
                get { return this; }
            }
    
            public virtual void CopyTo(Array arr, int index)
            {
            }
    
            public virtual IEnumerator GetEnumerator()
            {
                return null;
            }
    
            public StoreItems()
            {
                counter = 0;
                items = new object[5];
            }
        }
    }
  4. Save the file

The Size of a Collection

 

A Fixed-Size Collection

In the next sections, we will see how to add values to a list of a database. As you add or insert values in a list, the Count property grows. If your collection is array-based, when you start it, you specify the number of values that the list will contain. In theory, you cannot add new values beyond that number. In reality, you can increase the size of an array and then add a new item. If your collection is a linked list, you are also not confined to the laws of space (unless your computer runs out of memory).

If you create a list whose number of values must be constant, the user cannot add values beyond the maximum allowed number. Therefore, before adding a value, you can first check whether the collection has a fixed size or not. To give you this information, the IList interface is equipped with a Boolean read-only property named IsFxedSize. This property simply lets the user know whether the collection has a fixed number of items.

Here is an example of implementing this property for the System.Collections.IList interface:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public virtual bool IsFixedSize
        {
            get { return false; }
        }
    }
}

Practical Learning Practical Learning: Implementing the IsFixedSize Property

  1. Change the StoreItems.cs file as follows:
     
    using System;
    using System.Collections;
    
    namespace MusicalInstrumentStore2a
    {
        [Serializable]
        public class StoreItems : IList
        {
            . . . No Change
    
            public virtual bool IsFixedSize
            {
                get { return false; }
            }
    
            public StoreItems()
            {
                counter = 0;
                items = new object[5];
            }
        }
    }
  2. Save the file

A Read-Only Collection

Most databases are meant to receive new values. If you want, you can create a list that cannot receive new values. To support this, the IList interface is equipped with the Boolean IsReadOnly property. If a list is read-only, it would prevent the clients from adding items to it.

Here is an example of implementing the IsReadOnly property for the System.Collections.IList interface:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public virtual bool IsReadOnly
        {
            get { return false; }
        }
    }
}

Practical Learning Practical Learning: Setting the Read-Only Effect

  1. Change the StoreItems.cs file as follows:
     
    using System;
    using System.Collections;
    
    namespace MusicalInstrumentStore2
    {
        [Serializable]
        public class StoreItems : IList
        {
            . . . No Change
    
            public virtual bool IsReadOnly
            {
                get { return false; }
            }
    
            public StoreItems()
            {
                counter = 0;
                items = new object[5];
            }
        }
    }
  2. If you try executing the application now, you would receive various errors indicating that the StoreItems class has not implemented all required methods. Therefore, to eliminate these errors and prepare the class for later sections, change the file as follows:
     
    using System;
    using System.Collections;
    
    namespace MusicalInstrumentStore2
    {
        [Serializable]
        public class StoreItems : IList
        {
            int counter;
            private object[] items;
    
            public virtual int Count
            {
                get { return counter; }
            }
    
            public virtual bool IsSynchronized
            {
                get { return false; }
            }
    
            public virtual object SyncRoot
            {
                get { return this; }
            }
    
            public virtual void CopyTo(Array arr, int index)
            {
            }
    
            public virtual IEnumerator GetEnumerator()
            {
                return null;
            }
    
            public virtual bool IsFixedSize
            {
                get { return false; }
            }
    
            public virtual bool IsReadOnly
            {
                get { return false; }
            }
    
            public virtual object this[int index]
            {
                get { return null; }
                set { }
            }
    
            // This method is used to add a new item to the collection
            public virtual int Add(object value)
            {
                return 0;
            }
    
            // This method can be used to insert an item at 
            // a certain position inside the collection
            public virtual void Insert(int index, Object value)
            {
            }
    
            // This method is used to find out whether the item 
            // passed as argument exists in the collection
            public virtual bool Contains(object value)
            {
                return false;
            }
    
            // This method is used to check whether the item passed as
            // argument exists in the collection. If so, it returns its index
            public virtual int IndexOf(object value)
            {
                return 0;
            }
    
            // This method is used to delete the item positioned 
            // at the index passed as argument
            public virtual void RemoveAt(int index)
            {
            }
    
            // This method first checks the existence of the item passed 
            //  as argument. If the item exists, the method deletes it
            public virtual void Remove(object value)
            {
            }
    
            // This methods deletes all items from the collection
            public virtual void Clear()
            {
            }
    
            public StoreItems()
            {
                counter = 0;
                items = new object[5];
            }
        }
    }
  3. Save the file

Populating the Collection

 

Adding an Item

As it should be obvious, the primary operation to perform on a list is to populate it with at least one value. To support this, the System.Collections.IList interface is equipped with a method named Add. Its syntax is:

int Add(object value);

This method takes one argument as the value to add to the list. If your collection is an array, you can first check that there is still enough room in the list to add a new item. In reality, this is never an issue with the System.Collections.IList interface:

If the method succeeds with the addition, it returns the position where the value was added in the list. This is usually the last position in the list.

Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public virtual int Add(object value)
        {
            // Check whether there is still room in
            // the array to add a new item
            if (counter < objects.Length)
            {
                // Since there is room, put the new item to the end
                objects[items] = value;
                // increase the number of items
                objects++;
                // Return the index of the item that was added
                return counter  - 1;
            } // Since the item could not be added, return a negative index
            else
                return -1;
        }
    }
}

Practical Learning Practical Learning: Adding an Item to the Collection

  1. Change the code of the StoreItems.Add() method as follows:
     
    // This method is used to add a new item to the collection
    public virtual int Add(object value)
    {
        // Find out if the array is getting too small for the next item(s)
        // If it is, increase its size by 5
        if (Count == items.Length)
            Array.Resize(ref items, items.Length + 5);
    
        if (counter < items.Length)
        {
            items[counter] = value;
            counter++;
            return counter - 1;
        }
        else
            return -1;
    }
  2. In the Class View, double-click ItemEditor
  3. In the top section of the file, add the following:
     
    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;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
  4. In the Solution Explorer, double-click ItemEditor.cs
  5. On the form, double-click the Create button and implement its event as follows:
     
    private void btnCreate_Click(object sender, EventArgs e)
    {
        FileStream stmStoreItem = null;
        var item = new StoreItem();
        var items = new StoreItems();
        var bfmStoreItem = new BinaryFormatter();
    
        // If this directory doesn't exist, create it
        Directory.CreateDirectory(@"C:\Musical Instrument Store");
        // This is the file that holds the list of items
        var Filename = @"C:\Musical Instrument Store\StoreItems.mis";
    
        // Create a random number that will be used to identify the item
        var rnd = new Random();
        txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
        // Make sure the user had selected a category
        if (cbxCategories.Text.Length == 0)
        {
            MessageBox.Show("You must specify the item's category");
            cbxCategories.Focus();
            return;
        }
    
        // Make sure the user had selected a type
        if (cbxTypes.Text.Length == 0)
        {
            MessageBox.Show("You must specify the item's type");
            cbxTypes.Focus();
            return;
        }
    
        // Make sure the user had entered a name/description
        if (txtItemName.Text.Length == 0)
        {
             MessageBox.Show("You must enter the name (or a " +
                             "short description) for the item");
             txtItemName.Focus();
             return;
        }
    
        // Make sure the user had typed a price for the item
        if (txtUnitPrice.Text.Length == 0)
        {
             MessageBox.Show("You must enter the price of the item");
             txtUnitPrice.Focus();
             return;
        }
    
        // Before saving the new item, find out if there was
        // already a file that holds the list of items
        // If that file exists, open it and store its items 
        // in our StoreItems list
        if (File.Exists(Filename))
        {
             stmStoreItem = new FileStream(Filename,
                                           FileMode.Open,
                                           FileAccess.Read,
                                           FileShare.Read);
    
             try
             {
                  // Retrieve the list of items from file
                  items = (StoreItems)bfmStoreItem.Deserialize(stmStoreItem);
              }
              finally
              {
                  stmStoreItem.Close();
              }
          }
    
          // Create the music item
          item.ItemNumber = txtItemNumber.Text;
          item.Category = cbxCategories.Text;
          item.Type = cbxTypes.Text;
          item.ItemName = txtItemName.Text;
          item.UnitPrice = double.Parse(txtUnitPrice.Text);
    
          // Call the Add method of our collection class to add the item
          items.Add(item);
    
          // Save the list
          stmStoreItem = new FileStream(Filename,
                                        FileMode.Create,
                                        FileAccess.Write,
                                        FileShare.Write);
    
          try
          {
              bfmStoreItem.Serialize(stmStoreItem, items);
    
              if (txtPicturePath.Text.Length != 0)
              {
                    FileInfo flePicture = new FileInfo(txtPicturePath.Text);
                    flePicture.CopyTo(@"C:\Musical Instrument Store\" +
                                      txtItemNumber.Text + flePicture.Extension);
              }
    
              // After saving the item, reset the form
              txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
              cbxCategories.Text = "";
              cbxTypes.Text = "";
              txtItemName.Text = "";
              txtUnitPrice.Text = "0.00";
              txtPicturePath.Text = "";
              pbxStoreItem.Image = null;
        }
        finally
        {
            stmStoreItem.Close();
        }
    }
  6. Save the file

Inserting an Item

When you call the System.Collections.IList.Add() method, it adds the new value to the end of the list. Sometimes, you will want the new value to be insert somewhere inside the list. To support this operation, both the System.Collections.IList and the System.Collections.Generic.IList interfaces provide a method named Insert. The syntax of the System.Collections.IList.Insert() method is:

void Insert(int index, object value);

The syntax of the System.Collections.Generic.IList.Insert() method is:

void Insert(int index, T value);

This method takes two arguments. The second argument is the value that will be inserted into the list. The argument must hold a valid value. Because this method takes an Object object, if your collection is using a different type of value, you may have to cast it to Object. The first argument is the index of the item that will precede the new one.

As mentioned for the System.Collections.IList. Add() method, there are a few things you should know about this operation's success or lack of it:

Locating an Item in the Collection

 

This Default Item of the Collection

While using a list, various operations require that you know the object you are currently accessing. To provide this operation, you must create an indexed property. This property should take an index and return the type of object that makes up the list. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public virtual object this[int index]
        {
            get { return objects[index]; }

            set
            {
                objects[index] = value;
            }
        }
    }
}

After creating this property, you can then access an item using its index and applying the [] operator on its instance. Remember that if you want to use foreach, you must appropriately implement the IEnumerable.GetEnumerator() method.

Practical Learning Practical Learning: Identifying this Item in the Collection

  1. In the Class View, click StoreItems
  2. In the lower part of the Class View, double-click this[int]
  3. Change the code of the property as follows:
     
    public virtual object this[int index]
    {
        get { return items[index]; }
        set { items[index] = value; }
    }
  4. In the Solution Explorer, double-click ItemEditor.cs
  5. Double-click an unoccupied area of the form and implement its Load event as follows:
     
    private void ItemEditor_Load(object sender, EventArgs e)
    {
        // Since all values seem ready, prepare to process the item
        var item = new StoreItem();
        var items = new StoreItems();
        var bfmStoreItem = new BinaryFormatter();
    
        // This is the file that holds the list of items
        var Filename = @"C:\Musical Instrument Store\StoreItems.mis";
    
        if (File.Exists(Filename))
        {
            var stmStoreItem = new FileStream(Filename,
                                                     FileMode.Open,
                                                     FileAccess.Read,
                                                     FileShare.Read);
    
            try
            {
                // Retrieve the list of items from file
                items = (StoreItems)bfmStoreItem.Deserialize(stmStoreItem);
    
                // Display the categories in the combo box
                for (var i = 0; i < items.Count; i++)
                {
                    item = (StoreItem)items[i];
    
                    if (!cbxCategories.Items.Contains(item.Category))
                        cbxCategories.Items.Add(item.Category);
                }
    
                // Display the items types in the combo box
                for (var i = 0; i < items.Count; i++)
                {
                    item = (StoreItem)items[i];
    
                    if (!cbxTypes.Items.Contains(item.Type))
                        cbxTypes.Items.Add(item.Type);
                }
            }
            finally
            {
                stmStoreItem.Close();
            }
        }
        else
        {
            // Create a random number that will be used
    	// to identify the item
            var rnd = new Random();
            txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
            // Make sure the user had selected a category
            cbxCategories.Text = "";
            cbxTypes.Text = "";
        }
    }
  6. In the Solution Explorer, right-click MusicStore.cs and click View Code
  7. Make the following changes:
     
    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;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace MusicalInstrumentStore2
    {
        public partial class MusicStore : Form
        {
            StoreItems items;
            int iFilename;
            bool IsNewCustomerOrder;
    
            public MusicStore()
            {
                InitializeComponent();
            }
    
            internal void LoadMusicStore()
            {
                // Since all values seem ready, prepare to process the item
                items = new StoreItems();
                var bfmStoreItem = new BinaryFormatter();
    
                // This is the file that holds the list of items
                var Filename = @"C:\Musical Instrument Store\StoreItems.mis";
    
                if (File.Exists(Filename))
                {
                    FileStream stmStoreItem = new FileStream(Filename,
                                                             FileMode.Open,
                                                             FileAccess.Read,
                                                             FileShare.Read);
    
                    try
                    {
                        // Retrieve the list of items from file
                        items = (StoreItems)bfmStoreItem.Deserialize(stmStoreItem);
    
                        // Display the categories in the combo box
                        for (int i = 0; i < items.Count; i++)
                        {
                            StoreItem item = (StoreItem)items[i];
    
                            if (!cbxCategories.Items.Contains(item.Category))
                                cbxCategories.Items.Add(item.Category);
                        }
                    }
                    finally
                    {
                        stmStoreItem.Close();
                    }
                }
            }
        }
    }
  8. Return to the Music Store form
  9. On the form, double-click New Store Item
  10. Implement the event as follows:
    private void btnNewStoreItem_Click(object sender, EventArgs e)
    {
        var editor = new ItemEditor();
    
        // Create a random number to get it ready for
        // the user creating a new store item
        var rnd = new Random();
        editor.txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
        if (editor.ShowDialog() == DialogResult.Cancel)
            LoadMusicStore();
    }
  11. Return to the Music Store form
  12. Double-click the Item Category combo box and implement its event as follows:
     
    private void cbxCategories_SelectedIndexChanged(object sender, EventArgs e)
    {
        cbxTypes.Items.Clear();
        cbxTypes.Text = "";
        lvwStoreItems.Items.Clear();
        pbxStoreItem.Image = null;
    
        // If the current store inventory is empty, don't do anything
        if (items.Count == 0)
            return;
    
        // Get the item selected in the combo box
        var strCategory = (string)cbxCategories.SelectedItem;
    
        // Before doing anything, remove everything from the Types combo box
        // This eliminates the possibility of adding the same item(s) that
        // would exist already in the combo box
        cbxTypes.Items.Clear();
    
        // Check each item from the store inventory
        for (var i = 0; i < items.Count; i++)
        {
    	// Get the current item from the store inventory
            var item = (StoreItem)items[i];
    
    	// If that item is the same as the one selected in the combo box...
            if (item.Category == strCategory)
            {
    	    // ... get ready to add its corresponding type
    	    // But check first that the type is not
    	    // already in the Types combo box
    	    // If it's not yet there, then add it
                if (!cbxTypes.Items.Contains(item.Type))
                    cbxTypes.Items.Add(item.Type);
            }
        }
    }
  13. Return to the Music Store form
  14. Double-click the Item Type combo box and implement its event as follows:
     
    private void cbxTypes_SelectedIndexChanged(object sender, EventArgs e)
    {
        cbxTypes.Text = "";
        pbxStoreItem.Image = null;
    
        // If the current store inventory is empty, don't do anything
        if (items.Count == 0)
            return;
    
        // Get the item selected in the Categories combo box
        string strCategory = (string)cbxCategories.SelectedItem;
        // Get the item selected in theTypes combo box
        string strType = (string)cbxTypes.SelectedItem;
    
        // Empty the Available Items list view because 
        // we are about to (re)populate it
        lvwStoreItems.Items.Clear();
    
        // Check each item from the store inventory
        for (int i = 0; i < items.Count; i++)
        {
    	// Get the current item from the inventory
            StoreItem item = (StoreItem)items[i];
    
    	// If the category of that item is the same as the one 
    	// selected in the combo box and the type of that item is 
    	// the same as the one selected in the Types combo box...
            if ((item.Category == strCategory) &&
                (item.Type == strType))
            {
    	    // ... then display it in the Available Items list view
                ListViewItem lviStoreItem =
                    lvwStoreItems.Items.Add(item.ItemNumber);
                lviStoreItem.SubItems.Add(item.ItemName);
                lviStoreItem.SubItems.Add(item.UnitPrice.ToString("F"));
            }
        }
    }
  15. Return to the Music Store form
  16. On the form, double-click the Available Items list view and implement its SelectedIndexChanged event as follows:
     
    private void lvwStoreItems_SelectedIndexChanged(object sender, EventArgs e)
    {
        StoreItem item = new StoreItem();
    
        if ((lvwStoreItems.SelectedItems.Count == 0) ||
            (lvwStoreItems.SelectedItems.Count > 1))
            return;
    
        string strItemNumber =
    	lvwStoreItems.SelectedItems[0].SubItems[0].Text;
    
        for (int i = 0; i < items.Count; i++)
        {
            StoreItem itm = (StoreItem)items[i];
            if (itm.ItemNumber == strItemNumber)
                item = itm;
        }
    
        // Make a list of the picture files
        string strDirectory = @"C:\Musical Instrument Store";
        DirectoryInfo dirStoreItems = new DirectoryInfo(strDirectory);
        FileInfo[] PictureFiles = dirStoreItems.GetFiles("*.jpg");
    
        // Look for a file that holds the same name as the item number
        foreach (FileInfo fle in PictureFiles)
        {
            // Get the name of the file without its extension
            string fwe = Path.GetFileNameWithoutExtension(fle.FullName);
    
            if (fwe == strItemNumber)
                pbxStoreItem.Image = Image.FromFile(strDirectory + 
    		"\\" + item.ItemNumber + ".jpg");
        }
    }
  17. Return to the Music Store form
  18. Click the first text box under the Prop # label
  19. In the Properties window, click the Events button and double-click Leave
  20. Implement the event as follows:
     
    internal void CalculateOrder()
    {
        // Calculate the current total order and update the order
        double subTotal1 = 0.00, subTotal2 = 0.00, subTotal3 = 0.00,
               subTotal4 = 0.00, subTotal5 = 0.00, subTotal6 = 0.00;
        double itemsTotal = 0.00, taxRate = 0.00,
               taxAmount = 0.00, orderTotal = 0.00;
    
        // Retrieve the value of each sub total
        try
        {
            subTotal1 = double.Parse(this.txtSubTotal1.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        try
        {
            subTotal2 = double.Parse(this.txtSubTotal2.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        try
        {
            subTotal3 = double.Parse(this.txtSubTotal3.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        try
        {
            subTotal4 = double.Parse(this.txtSubTotal4.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        try
        {
            subTotal5 = double.Parse(this.txtSubTotal5.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        try
        {
            subTotal6 = double.Parse(this.txtSubTotal6.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Value");
        }
    
        // Calculate the total value of the sub totals
        itemsTotal = subTotal1 + subTotal2 + subTotal3 +
                     subTotal4 + subTotal5 + subTotal6;
    
        // Display the total order in the appropriate text box
        txtItemsTotal.Text = itemsTotal.ToString();
    
        try
        {
            taxRate = double.Parse(txtTaxRate.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid Tax Rate");
            txtTaxRate.Text = "7.75";
            txtTaxRate.Focus();
        }
    
        taxAmount = itemsTotal * taxRate / 100;
        orderTotal = itemsTotal + taxAmount;
    
        txtTaxAmount.Text = taxAmount.ToString("F");
        txtOrderTotal.Text = orderTotal.ToString("F");
    }
    
    private void txtItemNumber1_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber1.Text;
    
        foreach(StoreItem itm in items)
        {
            if (itm.ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription1.Text = itm.ItemName;
                txtUnitPrice1.Text = itm.UnitPrice.ToString("F");
                txtQuantity1.Text = "1";
                txtSubTotal1.Text = itm.UnitPrice.ToString("F");
    
    	    CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription1.Text = "";
            txtUnitPrice1.Text = "0.00";
            txtQuantity1.Text = "0";
            txtSubTotal1.Text = "0.00";
        }
    }
  21. Return to the Music Store form
  22. On the form, click the top Unit Price text box
  23. Press and hold Shift
  24. Click the top Qty text box and release Shift
  25. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice1_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        // Get the quantity of the current item
        try
        {
            qty = int.Parse(this.txtQuantity1.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid quantity value for item 1");
        }
    
        // Get the unit price of the current item
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice1.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 1");
        }
    
        // Calculate the current sub total
        subTotal = qty * unitPrice;
    
        // Display the new sub total in the corresponding text box
        txtSubTotal1.Text = subTotal.ToString();
    
        btnRemove1.Enabled = true;
    
        // Update the order
        CalculateOrder();
    }
  26. Return to the Music Store form
  27. On the form, double-click the top Remove button and implement the event as follows:
     
    private void btnRemove1_Click(object sender, EventArgs e)
    {
        txtItemNumber1.Text = "";
        txtDescription1.Text = "";
        txtUnitPrice1.Text = "0.00";
        txtQuantity1.Text = "0";
        txtSubTotal1.Text = "0.00";
        btnRemove1.Enabled = false;
    
        CalculateOrder();
    }
  28. Return to the Music Store form
  29. On the form, click the second text box under the Prop # label
  30. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtItemNumber2_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber2.Text;
    
        for (int i = 0; i < items.Count; i++ )
        {
            item = (StoreItem)items[i];
    
            if (item.ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription2.Text = item.ItemName;
                txtUnitPrice2.Text = item.UnitPrice.ToString("F");
                txtQuantity2.Text = "1";
                txtSubTotal2.Text = item.UnitPrice.ToString("F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription2.Text = "";
            txtUnitPrice2.Text = "0.00";
            txtQuantity2.Text = "0";
            txtSubTotal2.Text = "0.00";
        }
    }
  31. Return to the Music Store form
  32. On the form, click the second Unit Price text box
  33. Press and hold Shift
  34. Click the second Qty text box and release Shift
  35. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice2_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        try
        {
            qty = int.Parse(this.txtQuantity2.Text);
        }
        catch (FormatException)
        {
            // MessageBox.Show("Invalid quantity value for item 2");
        }
    
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice2.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 2");
        }
    
        subTotal = qty * unitPrice;
        this.txtSubTotal2.Text = subTotal.ToString();
    
        btnRemove2.Enabled = true;
        CalculateOrder();
    }
  36. Return to the Music Store form
  37. On the form, double-click the second Remove button and implement the event as follows:
     
    private void btnRemove2_Click(object sender, EventArgs e)
    {
        txtItemNumber2.Text = "";
        txtDescription2.Text = "";
        txtUnitPrice2.Text = "0.00";
        txtQuantity2.Text = "0";
        txtSubTotal2.Text = "0.00";
        btnRemove2.Enabled = false;
    
        CalculateOrder();
    }
  38. Return to the Music Store form
  39. On the form, click the third text box under the Prop # label
  40. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtItemNumber3_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber3.Text;
    
        for (int i = 0; i < items.Count; i++ )
        {
            item = (StoreItem)items[i];
    
            if (item.ItemNumber == strItemNumber)
            {
            {
                ItemFound = true;
                txtDescription3.Text = item.ItemName;
                txtUnitPrice3.Text = item.UnitPrice.ToString("F");
                txtQuantity3.Text = "1";
                txtSubTotal3.Text = item.UnitPrice.ToString("F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription3.Text = "";
            txtUnitPrice3.Text = "0.00";
            txtQuantity3.Text = "0";
            txtSubTotal3.Text = "0.00";
        }
    }
  41. Return to the Music Store form
  42. On the form, click the third Unit Price text box
  43. Press and hold Shift
  44. Click the third Qty text box and release Shift
  45. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice3_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        try
        {
            qty = int.Parse(this.txtQuantity3.Text);
        }
        catch (FormatException)
        {
            // MessageBox.Show("Invalid quantity value for item 3");
        }
    
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice3.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 3");
        }
    
        subTotal = qty * unitPrice;
        this.txtSubTotal3.Text = subTotal.ToString();
    
        btnRemove3.Enabled = true;
        CalculateOrder();
    }
  46. Return to the Music Store form
  47. On the form, double-click the third Remove button and implement the event as follows:
     
    private void btnRemove3_Click(object sender, EventArgs e)
    {
        txtItemNumber3.Text = "";
        txtDescription3.Text = "";
        txtUnitPrice3.Text = "0.00";
        txtQuantity3.Text = "0";
        txtSubTotal3.Text = "0.00";
        btnRemove3.Enabled = false;
    
        CalculateOrder();
    }
  48. Return to the Music Store form
  49. On the form, click the fourth text box under the Prop # label
  50. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtItemNumber4_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber4.Text;
    
        for (int i = 0; i < items.Count; i++ )
        {
            item = (StoreItem)items[i];
    
            if (item.ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription4.Text = item.ItemName;
                txtUnitPrice4.Text = item.UnitPrice.ToString("F");
                txtQuantity4.Text = "1";
                txtSubTotal4.Text = item.UnitPrice.ToString("F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription4.Text = "";
            txtUnitPrice4.Text = "0.00";
            txtQuantity4.Text = "0";
            txtSubTotal4.Text = "0.00";
        }
    }
  51. Return to the Music Store form
  52. On the form, click the fourth Unit Price text box
  53. Press and hold Shift
  54. Click the fourth Qty text box and release Shift
  55. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice4_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        try
        {
            qty = int.Parse(this.txtQuantity4.Text);
        }
        catch (FormatException)
        {
            // MessageBox.Show("Invalid quantity value for item 4");
        }
    
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice4.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 4");
        }
    
        subTotal = qty * unitPrice;
        this.txtSubTotal4.Text = subTotal.ToString();
    
        btnRemove4.Enabled = true;
        CalculateOrder();
    }
  56. Return to the Music Store form
  57. On the form, double-click the fourth Remove button and implement the event as follows:
     
    private void btnRemove4_Click(object sender, EventArgs e)
    {
        txtItemNumber4.Text = "";
        txtDescription4.Text = "";
        txtUnitPrice4.Text = "0.00";
        txtQuantity4.Text = "0";
        txtSubTotal4.Text = "0.00";
        btnRemove4.Enabled = false;
    
        CalculateOrder();
    }
  58. Return to the Music Store form
  59. On the form, click the fifth text box under the Prop # label
  60. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtItemNumber5_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber5.Text;
    
        for (int i = 0; i < items.Count; i++ )
        {
            item = (StoreItem)items[i];
    
            if (item.ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription5.Text = item.ItemName;
                txtUnitPrice5.Text = item.UnitPrice.ToString("F");
                txtQuantity5.Text = "1";
                txtSubTotal5.Text = item.UnitPrice.ToString("F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription5.Text = "";
            txtUnitPrice5.Text = "0.00";
            txtQuantity5.Text = "0";
            txtSubTotal5.Text = "0.00";
        }
    }
  61. Return to the Music Store form
  62. On the form, click the fifth Unit Price text box
  63. Press and hold Shift
  64. Click the fifth Qty text box and release Shift
  65. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice5_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        try
        {
            qty = int.Parse(this.txtQuantity5.Text);
        }
        catch (FormatException)
        {
            // MessageBox.Show("Invalid quantity value for item 5");
        }
    
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice5.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 5");
        }
    
        subTotal = qty * unitPrice;
        this.txtSubTotal5.Text = subTotal.ToString();
    
        btnRemove5.Enabled = true;
        CalculateOrder();
    }
  66. Return to the Music Store form
  67. On the form, double-click the fifth Remove button and implement the event as follows:
     
    private void btnRemove5_Click(object sender, EventArgs e)
    {
        txtItemNumber5.Text = "";
        txtDescription5.Text = "";
        txtUnitPrice5.Text = "0.00";
        txtQuantity5.Text = "0";
        txtSubTotal5.Text = "0.00";
        btnRemove5.Enabled = false;
    
        CalculateOrder();
    }
  68. Return to the Music Store form
  69. On the form, click the last text box under the Prop # label
  70. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtItemNumber6_Leave(object sender, EventArgs e)
    {
        bool ItemFound = false;
        StoreItem item = new StoreItem();
        string strItemNumber = txtItemNumber6.Text;
    
        for (int i = 0; i < items.Count; i++ )
        {
            item = (StoreItem)items[i];
    
            if (item.ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription6.Text = item.ItemName;
                txtUnitPrice6.Text = item.UnitPrice.ToString("F");
                txtQuantity6.Text = "1";
                txtSubTotal6.Text = item.UnitPrice.ToString("F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            MessageBox.Show("There is no store item with that number");
            txtDescription6.Text = "";
            txtUnitPrice6.Text = "0.00";
            txtQuantity6.Text = "0";
            txtSubTotal6.Text = "0.00";
        }
    }
  71. Return to the Music Store form
  72. On the form, click the sixth Unit Price text box
  73. Press and hold Shift
  74. Click the sixth Qty text box and release Shift
  75. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtUnitPrice6_Leave(object sender, EventArgs e)
    {
        int qty = 0;
        decimal unitPrice = 0.00M, subTotal = 0.00M;
    
        try
        {
            qty = int.Parse(this.txtQuantity6.Text);
        }
        catch (FormatException)
        {
            // MessageBox.Show("Invalid quantity value for item 6");
        }
    
        try
        {
            unitPrice = decimal.Parse(this.txtUnitPrice6.Text);
        }
        catch (FormatException)
        {
            MessageBox.Show("Invalid unit price for item 6");
        }
    
        subTotal = qty * unitPrice;
        this.txtSubTotal6.Text = subTotal.ToString();
    
        btnRemove6.Enabled = true;
        CalculateOrder();
    }
  76. Return to the Music Store form
  77. On the form, double-click the sixth Remove button and implement the event as follows:
     
    private void btnRemove6_Click(object sender, EventArgs e)
    {
        txtItemNumber6.Text = "";
        txtDescription6.Text = "";
        txtUnitPrice6.Text = "0.00";
        txtQuantity6.Text = "0";
        txtSubTotal6.Text = "0.00";
        btnRemove6.Enabled = false;
    
        CalculateOrder();
    }
  78. Return to the Music Store form
  79. On the form, click the Tax Rate text box
  80. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    private void txtTaxRate_Leave(object sender, EventArgs e)
    {
        CalculateOrder();
    }
  81. Return to the Music Store form
  82. Double-click the New Order button and implement its event as follows:
     
    private void btnNewCustomerOrder_Click(object sender, EventArgs e)
    {
        // We will store our files in the following folder    
        var strDirectory = @"C:\Musical Instrument Store\Receipts";
        var dirInfo = Directory.CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        var fleList = dirInfo.GetFiles();
        var Filename = "";
    
        // If there is no file in the directory,
        // then we will use 1000 as the first file name
        if (fleList.Length == 0)
        {
            iFilename = 1000;
        }
        else // If there was at least one file in the directory
        {
            // Get a reference to the last file
            var LastFile = fleList[fleList.Length - 1];
            // Get the name of the last file without its extension
            var fwe = Path.GetFileNameWithoutExtension(LastFile.FullName);
            // Increment the name of the file by 1
            iFilename = int.Parse(fwe) + 1;
        }
    
        // Update our global name of the file
        Filename = strDirectory + "\\" + iFilename.ToString() + ".cos";
        txtReceiptNumber.Text = iFilename.ToString();
    
        cbxCategories.Text = "";
        cbxTypes.Text = "";
        lvwStoreItems.Items.Clear();
    
        txtItemNumber1.Text = "";
        txtDescription1.Text = "";
        txtUnitPrice1.Text = "0.00";
        txtQuantity1.Text = "0";
        txtSubTotal1.Text = "0.00";
    
        txtItemNumber2.Text = "";
        txtDescription2.Text = "";
        txtUnitPrice2.Text = "0.00";
        txtQuantity2.Text = "0";
        txtSubTotal2.Text = "0.00";
    
        txtItemNumber3.Text = "";
        txtDescription3.Text = "";
        txtUnitPrice3.Text = "0.00";
        txtQuantity3.Text = "0";
        txtSubTotal3.Text = "0.00";
    
        txtItemNumber4.Text = "";
        txtDescription4.Text = "";
        txtUnitPrice4.Text = "0.00";
        txtQuantity4.Text = "0";
        txtSubTotal4.Text = "0.00";
    
        txtItemNumber5.Text = "";
        txtDescription5.Text = "";
        txtUnitPrice5.Text = "0.00";
        txtQuantity5.Text = "0";
        txtSubTotal5.Text = "0.00";
    
        txtItemNumber6.Text = "";
        txtDescription6.Text = "";
        txtUnitPrice6.Text = "0.00";
        txtQuantity6.Text = "0";
        txtSubTotal6.Text = "0.00";
    
        txtItemsTotal.Text = "0.00";
        txtTaxRate.Text = "7.75";
        txtTaxAmount.Text = "0.00";
        txtOrderTotal.Text = "0.00";
    }
  83. Return to the Music Store form
  84. Double-click the Save button and implement the event as follows:
     
    private void btnSave_Click(object sender, EventArgs e)
    {
        // We will store our files in the following folder    
        var strDirectory = @"C:\Musical Instrument Store\Receipts";
        var dirInfo = Directory.CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        FileInfo[] fleList = dirInfo.GetFiles();
        var Filename = "";
    
        // If this is a new customer order,
        // get ready to create a name for the file
        if (IsNewCustomerOrder == true)
        {
            // If there is no file in the directory,
            // then we will use 1000 as the first file name
            if (fleList.Length == 0)
            {
                iFilename = 1000;
            }
            else // If there was at least one file in the directory
            {
                // Get a reference to the last file
                var LastFile = fleList[fleList.Length - 1];
                // Get the name of the last file without its extension
                var fwe = Path.GetFileNameWithoutExtension(LastFile.FullName);
                // Increment the name of the file by 1
                iFilename = int.Parse(fwe) + 1;
            }
    
            // Update our global name of the file
            Filename = strDirectory + "\\" + iFilename.ToString() + ".cos";
            txtReceiptNumber.Text = iFilename.ToString();
    
            IsNewCustomerOrder = false;
        } // If a cleaning order was already opened, we will simply update it
        else
            Filename = @"C:\Musical Instrument Store\Receipts\" +
                        txtReceiptNumber.Text + ".cos";
    
        var wrtCustomerOrder = new StreamWriter(Filename);
    
        try
        {
            wrtCustomerOrder.WriteLine(txtItemNumber1.Text);
            wrtCustomerOrder.WriteLine(txtDescription1.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice1.Text);
            wrtCustomerOrder.WriteLine(txtQuantity1.Text);
    
            wrtCustomerOrder.WriteLine(txtItemNumber2.Text);
            wrtCustomerOrder.WriteLine(txtDescription2.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice2.Text);
            wrtCustomerOrder.WriteLine(txtQuantity2.Text);
    
            wrtCustomerOrder.WriteLine(txtItemNumber3.Text);
            wrtCustomerOrder.WriteLine(txtDescription3.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice3.Text);
            wrtCustomerOrder.WriteLine(txtQuantity3.Text);
    
            wrtCustomerOrder.WriteLine(txtItemNumber4.Text);
            wrtCustomerOrder.WriteLine(txtDescription4.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice4.Text);
            wrtCustomerOrder.WriteLine(txtQuantity4.Text);
    
            wrtCustomerOrder.WriteLine(txtItemNumber5.Text);
            wrtCustomerOrder.WriteLine(txtDescription5.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice5.Text);
            wrtCustomerOrder.WriteLine(txtQuantity5.Text);
    
            wrtCustomerOrder.WriteLine(txtItemNumber6.Text);
            wrtCustomerOrder.WriteLine(txtDescription6.Text);
            wrtCustomerOrder.WriteLine(txtUnitPrice6.Text);
            wrtCustomerOrder.WriteLine(txtQuantity6.Text);
    
            wrtCustomerOrder.WriteLine(txtItemsTotal.Text);
            wrtCustomerOrder.WriteLine(txtTaxRate.Text);
        }
        finally
        {
            wrtCustomerOrder.Close();
        }
    }
  85. Return to the Music Store Form
  86. Double-click the Open button and implement its event as follows:
     
    private void btnOpen_Click(object sender, EventArgs e)
    {
        var strDirectory = @"C:\Musical Instrument Store\Receipts";
        var strFilename  = 
    		@"C:\Musical Instrument Store\Receipts\1000.cos";
    
        if (txtReceiptNumber.Text == "")
            return;
        else
        {
            try
            {
                strFilename = strDirectory + "\\" +
                                      txtReceiptNumber.Text + ".cos";
    
                var rdrCustomerOrder = new StreamReader(strFilename);
    
                try
                {
                    txtItemNumber1.Text = rdrCustomerOrder.ReadLine();
                    txtDescription1.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice1.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity1.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice1_Leave(sender, e);
    
                    txtItemNumber2.Text = rdrCustomerOrder.ReadLine();
                    txtDescription2.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice2.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity2.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice2_Leave(sender, e);
    
                    txtItemNumber3.Text = rdrCustomerOrder.ReadLine();
                    txtDescription3.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice3.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity3.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice3_Leave(sender, e);
    
                    txtItemNumber4.Text = rdrCustomerOrder.ReadLine();
                    txtDescription4.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice4.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity4.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice4_Leave(sender, e);
    
                    txtItemNumber5.Text = rdrCustomerOrder.ReadLine();
                    txtDescription5.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice5.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity5.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice5_Leave(sender, e);
    
                    txtItemNumber6.Text = rdrCustomerOrder.ReadLine();
                    txtDescription6.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice6.Text = rdrCustomerOrder.ReadLine();
                    txtQuantity6.Text = rdrCustomerOrder.ReadLine();
                    txtUnitPrice6_Leave(sender, e);
    
                    txtItemsTotal.Text = rdrCustomerOrder.ReadLine();
                    txtTaxRate.Text = rdrCustomerOrder.ReadLine();
    
                    CalculateOrder();
                    IsNewCustomerOrder = false;
                }
                finally
                {
                    rdrCustomerOrder.Close();
                }
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show("There is no customer order " +
    			    "with that receipt number");
            }
        }
    }
  87. Return to the Music Store form
  88. Double-click an unoccupied area of the form and implement the event as follows:
     
    private void MusicStore_Load(object sender, EventArgs e)
    {
        btnNewCustomerOrder_Click(sender, e);
        LoadMusicStore();
        IsNewCustomerOrder = true;
    }
  89. Return to the Music Store form
  90. Double-click the Close and implement its Click event as follows:
     
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  91. Execute the application to test it
  92. Access the Item Editor dialog box and create a few items as follows (let the computer create the item numbers):
     
    Category Type Item Name Unit Price Picture
    Guitars Electric Gibson Les Paul Vintage Mahogany Electric Guitar 745.95 Picture
    Bass Electric 4-String Epiphone Thunderbird IV Bass 325.85 Picture
    Keyboards Synthesizers Alesis QS8.2 88 Key Synthesizer 825.50 Picture
    Guitars Acoustic Gretsch Guitars G100 Synchromatic Archtop Acoustic Guitar 595.95 Picture
    Drums Drum Set Pulse Pro 5-Piece Drum Set with Cymbals 395.95 Picture
    Keyboards Pianos Roland RD-700SX Digital Piano 2195.00  
    Accessories Cables Mogami Gold AES/EBU Interconnect Cable with Neutrik XLR 45.85  
    Guitars Acoustic-Electric Ibanez V Series V70CE Dreadnought Cutaway Acoustic-Electric Guitar 225.50  
    Guitars Electric Schecter C-1 Hellraiser Electric Guitar 650.00 Picture
    Keyboards Synthesizers Roland V Synth GT Elastic Audio Synthesizer Keyboard 2895.50 Picture
    Bass Electric 5-String Fender Jazz Bass 24 V 5-String Bass Guitar 825.50 Picture
    Guitars Electric Fender Standard Stratocaster Left-Handed Electric Guitar 425.85 Picture
    Recording Microphone MXL V63M Studio Condenser Microphone 72.95 Picture
    Guitars Acoustic Yamaha FD01S Acoustic Folk Guitar 185.95  
    Book/CD/DVD Instructional Hal Leonard Amazing Phrasing - Alto Sax (Book/CD) 18.00  
    Guitars Classical & Nylon Alvarez Artist Series AC60S Classical Acoustic Guitar 275.95 Picture
    Guitars Acoustic Washburn D100DL Acoustic Guitar 150.50 Picture
    Drums Electronic Percussion Boss DR-670 Dr. Rhythm Drum Machine 275.85 Picture
    Recording Microphone Shure SM58 Mic 95.95 Picture
    Accessories Cables Live Wire HPE325 Headphone and Extension Cable 10.95 Picture
    Bass Acoustic Fretted Ibanez AEB10E Acoustic-Electric Bass Guitar with Onboard Tuner 350.00 Picture
    Drums World Percussion Latin Percussion Conga 3-Pack with Bongos 595.95 Picture
    Keyboards Synthesizers Roland JUNO-D 61-Key Synthesizer 595.95 Picture
    Drums World Percussion Latin Percussion Aspire Conga Set with Bongos and Stand 425.50 Picture
    Recording Microphone AKG Perception 200 Condenser Microphone 160.00 Picture
     
    Musical Instrument Store: Item Category
  93. Create a few customers' orders and click Save then New Order each time. Here are examples:
     
    Musical Instrument Store: Customer Order
    Musical Instrument Store: Customer Order
  94. Close the form and return to your programming environment

Enumerating the Collection foreach Item

One of the most valuables features of the C# is the ability to use the foreach loop to enumerate the members of a collection. To make this possible, you must implement the IEnumerator interface in your collection class. Following the rules of interface implementation, you must override the members of IEnumerator

Checking the Existence of an Item

One of the routine operations you can perform on a list is to find out whether it contains a certain value. To assist you with this operation, the System.Collections.IList interface is equipped with a method named Contains. Its syntax is:

bool Contains(object value);

This method takes as argument the value to look for. If the value is found in the list, the method returns true. If no value is found in the collection, this method returns false.

Here is an example of implementing this method:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public bool Contains(object value)
        {
            for (int i = 0; i < Count; i++)
                if (objects[i] == value)
                    return true;
            return false;
        }
    }
}

This method calls the Equals() method of the objects that make up the list to find out whether the value argument exists in the collection. If this method produces a wrong result, especially if you are using your own class to represent the item, you may have to override your own Equals() method.

Getting the Index of an Item

The System.Collections.IList.Contains() method is used to check whether a particular value (already) exists in the collection. If you know that a certain item exists in the collection but you don't know its index inside the list, the IList interface can assist you through a method named IndexOf. Its syntax is:

int IndexOf(object value);

This method takes as argument the value to look for in the list. If the value is found in the collection, the method returns its index. If there is no value defined like that, the method returns -1. Here is an example of implementing this method:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public int IndexOf(object value)
        {
            for (int i = 0; i < Count; i++)
                if (objects[i] == value)
                    return i;
            return -1;
        }
    }
}

This method calls the Equals() method of the objects that make up the collection to find out whether the value argument exists in the list. If this method produces a wrong result, especially if you are using your own class to represent the value, you may have to override your own Equals() method.

Deleting Values in the List

 

Deleting a Value by its Index

If a value is not necessary in your list, you can delete it. Probably the simplest way to delete a value is to specify its position in the list. To support this operation, both the System.Collections.IList and the System.Collections.Generic.IList interfaces are equipped with a method named RemoveAt. The syntax of the RemoveAt() method is is the same for both interfaces and it is:

void RemoveAt(int index);

This method takes as argument the index of the value to be removed. Here is an example:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public void RemoveAt(int index)
        {
            if ((index >= 0) && (index < Count))
            {
                for (int i = index; i < Count - 1; i++)
                    objects[i] = objects[i + 1];
                items--;
            }
        }
    }
}

Deleting an Item by its Value

The problem with deleting a value based on its index is that, if you are not sure, you could delete the wrong value. An alternative is to first precisely define the value you want to get rid of, and then hand the value itself to the compiler that would remove it. To support this approach, the System.Collections.IList interface is equipped with a method named Remove() and whose syntax is:

void Remove(object value);

This method takes as argument the value to be deleted. This means that the compiler will first look for the value in the list. If it finds that value, it removes it. If there is no value like that, nothing happens (the compiler doesn't throw an exception. Here is an example of implementing this method:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        . . . No Change

        public virtual void Remove(Object value)
        {
            RemoveAt(IndexOf(value));
        }
    }
}

Clearing a Collection

To remove all value from a list at once, you can implement Clear() method of the System.Collections.IList interface. Its syntax is:

void Clear();

Here is an example of implementing it:

using System;
using System.Collections;

namespace BookCollection
{
    public class BookList : IList
    {
        private int counter;
        private object[] objects;

        public BookList()
        {
            counter = 0;
            objects = new object[5];
        }

        public virtual int Count
        {
            get { return counter; }
        }

        public virtual bool IsSynchronized
        {
            get { return false; }
        }

        public virtual object SyncRoot
        {
            get { return this; }
        }

        public virtual void CopyTo(Array ary, int index)
        {
        }

        public IEnumerator GetEnumerator()
        {
            return null;
        }

        public virtual bool IsFixedSize
        {
            get { return false; }
        }

        public virtual bool IsReadOnly
        {
            get { return false; }
        }

        public virtual int Add(object value)
        {
            // Check whether there is still room in
            // the array to add a new item
            if (counter < objects.Length)
            {
                // Since there is room, put the new item to the end
                objects[counter] = value;
                // increase the number of items
                counter++;
                // Return the index of the item that was added
                return counter - 1;
            } // Since the item could not be added, return a negative index
            else
                return -1;
        }

        public virtual void Insert(int index, object value)
        {
        }

        public virtual object this[int index]
        {
            get { return objects[index]; }

            set
            {
                objects[index] = value;
            }
        }

        public virtual bool Contains(object value)
        {
            for (int i = 0; i < Count; i++)
                if (objects[i] == value)
                    return true;
            return false;
        }

        public virtual int IndexOf(object value)
        {
            for (int i = 0; i < Count; i++)
                if (objects[i] == value)
                    return i;
            return -1;
        }

        public virtual void RemoveAt(int index)
        {
            if ((index >= 0) && (index < Count))
            {
                for (int i = index; i < Count - 1; i++)
                    objects[i] = objects[i + 1];
                counter--;
            }
        }

        public virtual void Remove(Object value)
        {
            RemoveAt(IndexOf(value));
        }

        public virtual void Clear()
        {
            counter = 0;
        }
    }
}

Previous Copyright © 2008-2009 Yevol.com Next