Populating the Collection
|
|
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 there is still room in the collection, the value would be added to the
list
- If there is not enough room, the value would simply not be added. There
would not be a problem and the program would not crash. In fact, no
exception would be thrown if the value was not added because of lack of
space. On the other hand, since the compiler would not let you know that there
was a problem with "logistic", you may not know whether the value was added or not. Therefore, if you are concerned with
knowing whether the value was added, you must provide this functionality yourself
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:
Header File: BookList.h
#pragma once
using namespace System;
using namespace System::Collections;
public ref class CBookList : public IList
{
private:
int counter;
array<Object ^> ^ objects;
public:
CBookList(void);
virtual property int Count
{
int get() { return counter; }
}
virtual property bool IsSynchronized
{
bool get() { return false; }
}
virtual property Object ^ SyncRoot
{
Object ^ get() { return this; }
}
virtual void CopyTo(Array ^ ary, int index);
virtual IEnumerator ^ GetEnumerator();
virtual property bool IsFixedSize
{
bool get() { return false; }
}
virtual property bool IsReadOnly
{
bool get() { return false; }
}
virtual int Add(Object ^ value);
};
Source File: BookList.cpp
#include "BookList.h"
CBookList::CBookList(void)
: counter(0),
objects(gcnew array<Object ^>(5))
{
}
void CBookList::CopyTo(Array ^ ary, int index)
{
}
IEnumerator ^ CBookList::GetEnumerator()
{
return nullptr;
}
int CBookList::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;
}
Practical
Learning: Adding an Item to the Collection |
|
- Change the code of the CStoreItems::Add() method in the
StoreItems.cpp source file as follows:
// This method is used to add a new item to the collection
int CStoreItems::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(items, items->Length + 5);
if (counter < items->Length)
{
items[counter] = value;
counter++;
return counter - 1;
}
else
return -1;
}
|
- In the Class View, expand the MusicalInstrumentStore2 sub-folder.
Under MusicalInstrumentStore2, double-click ItemEditor
- In the top section of the file, add the following:
#pragma once
#include "CategoryEditor.h"
#include "TypeEditor.h"
#include "StoreItem.h"
#include "StoreItems.h"
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::IO;
using namespace System::Runtime::Serialization::Formatters::Binary;
|
- In the Solution Explorer, double-click ItemEditor.h
- On the form, double-click the Create button and implement its event
as follows:
System::Void btnCreate_Click(System::Object^ sender, System::EventArgs^ e)
{
FileStream ^ stmStoreItem = nullptr;
CStoreItem ^ item = gcnew CStoreItem;
CStoreItems ^ items = gcnew CStoreItems;
BinaryFormatter ^ bfmStoreItem = gcnew BinaryFormatter;
// If this directory doesn't exist, create it
Directory::CreateDirectory(L"C:\\Musical Instrument Store");
// This is the file that holds the list of items
String ^ Filename = "C:\\Musical Instrument Store\\StoreItems.mis";
// Create a random number that will be used to identify the item
Random ^ rnd = gcnew Random;
txtItemNumber->Text = rnd->Next(100000, 999999).ToString();
// Make sure the user had selected a category
if (cbxCategories->Text->Length == 0)
{
MessageBox::Show(L"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(L"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(L"You must enter the name (or a "
L"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(L"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 = gcnew FileStream(Filename,
FileMode::Open,
FileAccess::Read,
FileShare::Read);
try
{
// Retrieve the list of items from file
items =
dynamic_cast<CStoreItems ^>(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 = gcnew FileStream(Filename,
FileMode::Create,
FileAccess::Write,
FileShare::Write);
try
{
bfmStoreItem->Serialize(stmStoreItem, items);
if (txtPicturePath->Text->Length != 0)
{
FileInfo ^ flePicture = gcnew FileInfo(txtPicturePath->Text);
flePicture->CopyTo(L"C:\\Musical Instrument Store\\" +
txtItemNumber->Text + flePicture->Extension);
}
// After saving the item, reset the form
txtItemNumber->Text = rnd->Next(100000, 999999).ToString();
cbxCategories->Text = L"";
cbxTypes->Text = L"";
txtItemName->Text = L"";
txtUnitPrice->Text = L"0.00";
txtPicturePath->Text = L"";
pbxStoreItem->Image = nullptr;
}
finally
{
stmStoreItem->Close();
}
}
|
- Save the file
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 item);
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:
- If the index argument holds a negative value or a value higher than
the allowed number (for example if the list is an array) of the items
(depending on how you implement the method), the new value would not be
added, the compiler would not throw an exception, and therefore nothing
would let you know that the value was not added. If you want to find out
whether the value was formally or actually inserted or not, you must create
the functionality yourself
- If the value argument is not valid, again depending on how you
structure your class, either the value would not be inserted or something
else would go wrong. Fortunately, if the value argument is of the
type of
a class you created yourself, the compiler would produce an error such as
letting you know that the argument is holding a value that is not conform to its
property or member variable
|
|