Home

C++/CLI Collections:
Locating an Item in the Collection

 

This Default Item of the Collection

While using a collection, 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 collection. Here is an example:

using namespace System;
using namespace System::Collections;

public ref class CObjects : public IList
{
private:
    int items;
    array<Object ^> ^ objects;
public:
    . . . No Change

    virtual property Object ^ default[int]
    {
        Object ^ get(int index) { return objects[index]; }

        void set(int index, Object ^ value)
        {
            objects[index] = value;
        }
    }

    . . . No Change
};

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 for each, you must appropriately implement the IEnumerable::GetEnumerator() method.

Practical Learning Practical Learning: Identifying this Item in the Collection

  1. Access the Properties.h header file
  2. In the Scopes combo box of the Code Editor, select CProperties::default
  3. In the Functions combo box, select get
  4. Change the default property as follows:
     
    #pragma once
    
    #include "RentalProperty.h"
    
    using namespace System;
    using namespace System::Collections;
    
    public ref class CProperties : public IList
    {
    private:
        array<Object ^> ^ RentalProperties;
        int counter;
    	
    public:
        . . . No Change
    
        virtual property Object ^ default[int]
        {
    	Object ^ get(int index) { return RentalProperties[index]; }
    	void set(int index, Object ^ value)
    	{
    	    RentalProperties[index] = value;
    	}
        }
    
        . . . No Change
    };
  5. Access the Exercise.cpp source file and change the section of the for loop as follows:
     
    #include "RentalProperty.h"
    #include "Properties.h"
    
    using namespace System;
    
    int main()
    {
        . . . No Change
    
        Console::WriteLine(L"<+> Solas Properties Rental <+>");
        Console::WriteLine(L"<->   Properties Listing    <->");
        for(int i = 0; i < properties->Count; i++)
        {
            CRentalProperty ^ prop =
    		dynamic_cast<CRentalProperty ^>(properties[i]);
    	Console::WriteLine(L"---------------------------");
    	Console::WriteLine(L"{0}. Property Details",
                            (i+1).ToString());
    	Console::WriteLine(L"Property #:    {0}",
    			prop->PropertyCode);
    	Console::WriteLine(L"Property Type: {0}",
    			prop->PropertyType);
    	Console::WriteLine(L"Condition:     {0}",
    			prop->PropertyCondition);
    	Console::WriteLine(L"Bedrooms:      {0}",
    			prop->Bedrooms);
    	Console::WriteLine(L"Bathrooms:     {0}",
    			prop->Bathrooms);
    	Console::WriteLine(L"Monthly Rent:  {0}",
    			prop->MonthlyRent);
        }
        Console::WriteLine(L"================================");
        return 0;
    }
  6. Execute the application to see the result
  7. Close the DOS window
  8. Open the Properties.h header file
  9. To be able to use for each, make the following changes:
     
    #pragma once
    
    #include "RentalProperty.h"
    
    using namespace System;
    using namespace System::Collections;
    
    public ref class CProperties : public IList, IEnumerator
    {
    private:
        array<Object ^> ^ RentalProperties;
        int counter;
        int cur;
    	
    public:
        CProperties(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 property bool IsFixedSize
        {
    	bool get() { return false; }
        }
    
        virtual property bool IsReadOnly
        {
    	bool get() { return false; }
        }
    
        virtual property Object ^ default[int]
        {
    	Object ^ get(int index) { return RentalProperties[index]; }
    	void set(int index, Object ^ value)
    	{
    	    RentalProperties[index] = value;
    	}
        }
    
        property Object ^ Current
        {
            virtual Object ^ get()
            {
                try {
                    return this[cur];
                }
                catch(IndexOutOfRangeException ^)
                {
                    Console::WriteLine(L"The current rental property can be "
                                     L"accessed only within a valid range ");
                    return nullptr;
                }
            }
        }
    
        virtual void Reset();
        virtual bool MoveNext();
    
        virtual void CopyTo(Array ^, int);
        virtual IEnumerator ^ GetEnumerator(void);
    
        . . . No Change
    };
  10. Open the Properties.cpp source file and make the following changes:
     
    #include "Properties.h"
    
    CProperties::CProperties(void)
        : counter(0), cur(-1)
    {
        RentalProperties = gcnew array<Object ^>(5);
    }
    
    void CProperties::CopyTo(Array ^, int)
    {
    }
    
    void CProperties::Reset()
    {
        cur = -1;
    }
    bool CProperties::MoveNext()
    {
        cur++;
    
        if( cur < Count )
            return true;
        else
            return false;
    }
    
    IEnumerator ^ CProperties::GetEnumerator(void)
    {
        return this;
    }
    
    . . . No Change
  11. Open the Exercise.cpp source file and make the following changes:
     
    #include "RentalProperty.h"
    #include "Properties.h"
    
    using namespace System;
    
    int main()
    {
        . . . No Change
    
        int i = 1;
        Console::WriteLine(L"<+> Solas Properties Rental <+>");
        Console::WriteLine(L"<->   Properties Listing    <->");
        for each(CRentalProperty ^ prop in properties)
        {
    	Console::WriteLine(L"---------------------------");
    	Console::WriteLine(L"{0}. Property Details", i.ToString());
    	Console::WriteLine(L"Property #:    {0}",
    			prop->PropertyCode);
    	Console::WriteLine(L"Property Type: {0}",
    			prop->PropertyType);
    	Console::WriteLine(L"Condition:     {0}",
    			prop->PropertyCondition);
    	Console::WriteLine(L"Bedrooms:      {0}",
    			prop->Bedrooms);
    	Console::WriteLine(L"Bathrooms:     {0}",
    			prop->Bathrooms);
    	Console::WriteLine(L"Monthly Rent:  {0}",
    			prop->MonthlyRent);
    	i++;
        }
        Console::WriteLine(L"================================");
        return 0;
    }
  12. Close the DOS window

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 item. To assist you with this operation, the IList interface is equipped with a method named Contains. Its syntax is:

bool Contains(Object ^ item);

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

Here is an example of implementing this method:

public ref class CObjects : public IList
{
private:
    int items;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual int Add(Object ^);
    virtual void Insert(int, Object ^);
    virtual bool Contains(Object ^);
};

. . . No Change

bool CObjects::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 collection (in our example, that would be the objects array) to find out whether the item 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.

Practical Learning Practical Learning: Checking the Existence of an Item

  1. Open the RentalProperty.h header file and declare a virtual Equals() method as follows:
     
    #pragma once
    
    using namespace System;
    
    . . . No Change
    
    [Serializable]
    public ref class CRentalProperty
    {
    private:
        . . . No Change
    
    public:
        . . . No Change
    
    public:
        virtual bool Equals(CRentalProperty ^);
    
        // This constructor is used to create 
        // default values for a property
    	CRentalProperty(void);
    };
  2. Access the RentalProperty.cpp source file and implement the method as follows:
     
    #include "RentalProperty.h"
    
    CRentalProperty::CRentalProperty(void)
    {
        propCode = 0;
        type     = PropertyTypes::Unknown;
        cond     = PropertyConditions::Unknown;
        beds     = 0;
        baths    = 0.0;
        val      = 0.00;
    }
    
    bool CRentalProperty::Equals(CRentalProperty ^ prop)
    {
        if( (propCode == prop->PropertyCode) &&
    	(type     == prop->PropertyType) &&
    	(cond     == prop->PropertyCondition) &&
    	(beds     == prop->Bedrooms) &&
    	(baths    == prop->Bathrooms) &&
    	(val      == prop->MonthlyRent) )
    	return true;
        else
    	return false;
    }
  3. Open the Properties.cpp source file
  4. In the Functions combo box, select Contains and implement the method as follows:
     
    // This method is used to find out whether the item
    // passed as argument exists in the collection
    bool CProperties::Contains(Object ^ value)
    {
        bool found = false;
    
        for(int i = 0; i < Count; i++)
    	if( dynamic_cast<CRentalProperty ^>(
    	   this[i])->Equals(dynamic_cast<CRentalProperty ^>(value)) )
    		found = true;
    
        return found;
    }
  5. Open the Exercise.cpp source file and make the following changes:
     
    #include "RentalProperty.h"
    #include "Properties.h"
    
    using namespace System;
    
    int main()
    {
        CProperties ^ properties = gcnew CProperties;
        CRentalProperty ^ rental = nullptr;
    
        rental = gcnew CRentalProperty;
        rental->PropertyCode = 737495;
        rental->PropertyType = PropertyTypes::Apartment;
        rental->PropertyCondition = PropertyConditions::Good;
        rental->Bedrooms = 1;
        rental->Bathrooms = 1;
        rental->MonthlyRent = 950.00;
        properties->Add(rental);
    
        rental = gcnew CRentalProperty;
        rental->PropertyCode = 293749;
        rental->PropertyType = PropertyTypes::SingleFamily;
        rental->PropertyCondition = PropertyConditions::Excellent;
        rental->Bedrooms = 5;
        rental->Bathrooms = 3.5;
        rental->MonthlyRent = 2550.75;
        properties->Add(rental);
    
        rental = gcnew CRentalProperty;
        rental->PropertyCode = 224006;
        rental->PropertyType = PropertyTypes::Apartment;
        rental->PropertyCondition = PropertyConditions::Excellent;
        rental->Bedrooms = 2;
        rental->Bathrooms = 1;
        rental->MonthlyRent = 1250.55;
        properties->Add(rental);
    
        rental = gcnew CRentalProperty;
        rental->PropertyCode = 197249;
        rental->PropertyType = PropertyTypes::Townhouse;
        rental->PropertyCondition = PropertyConditions::BadShape;
        rental->Bedrooms = 4;
        rental->Bathrooms = 2.5;
        rental->MonthlyRent = 1750.65;
        properties->Add(rental);
    	
        rental = gcnew CRentalProperty;
        rental->PropertyCode = 592795;
        rental->PropertyType = PropertyTypes::SingleFamily;
    	rental->PropertyCondition = PropertyConditions::Good;
        rental->Bedrooms = 3;
        rental->Bathrooms = 2.00;
        rental->MonthlyRent = 1870.35;
        properties->Add(rental);
    
        int i = 1;
        Console::WriteLine(L"<+> Solas Properties Rental <+>");
        Console::WriteLine(L"<->   Properties Listing    <->");
        for each(CRentalProperty ^ prop in properties)
        {
    	Console::WriteLine(L"---------------------------");
    	Console::WriteLine(L"{0}. Property Details", i.ToString());
    	Console::WriteLine(L"Property #:    {0}",
    			prop->PropertyCode);
    	Console::WriteLine(L"Property Type: {0}",
    			prop->PropertyType);
    	Console::WriteLine(L"Condition:     {0}",
    			prop->PropertyCondition);
    	Console::WriteLine(L"Bedrooms:      {0}",
    			prop->Bedrooms);
    	Console::WriteLine(L"Bathrooms:     {0}",
    			prop->Bathrooms);
    	Console::WriteLine(L"Monthly Rent:  {0}",
    			prop->MonthlyRent);
    	i++;
        }
        Console::WriteLine(L"================================");
    
        CRentalProperty ^ item1 = gcnew CRentalProperty;
        item1->PropertyCode = 293749;
        item1->PropertyType = PropertyTypes::SingleFamily;
        item1->PropertyCondition = PropertyConditions::Excellent;
        item1->Bedrooms = 5;
        item1->Bathrooms = 3.5;
        item1->MonthlyRent = 2550.75;
    
        Console::WriteLine(L"8--8--8--8--8--8--8--8--8--8--8--8--8--8--8");
        Console::WriteLine(L"-=- Sample Property -=-");
        Console::WriteLine(L"Property #:    {0}",
    			item1->PropertyCode);
        Console::WriteLine(L"Property Type: {0}",
    			item1->PropertyType);
        Console::WriteLine(L"Condition:     {0}",
    			item1->PropertyCondition);
        Console::WriteLine(L"Bedrooms:      {0}",
    			item1->Bedrooms);
        Console::WriteLine(L"Bathrooms:     {0}",
    			item1->Bathrooms);
        Console::WriteLine(L"Monthly Rent:  {0}",
    			item1->MonthlyRent);
    
        Console::WriteLine(L"-------------------------------------------");
        if( properties->Contains(item1) == true )
    Console::WriteLine("That property already exists in the listing");
        else
    Console::WriteLine("The property was not found in our database");
    
        Console::WriteLine(L"8--8--8--8--8--8--8--8--8--8--8--8--8--8--8");
    
        CRentalProperty ^ item2 = gcnew CRentalProperty;
        item2->PropertyCode = 290004;
        item2->PropertyType = PropertyTypes::SingleFamily;
        item2->PropertyCondition = PropertyConditions::Excellent;
        item2->Bedrooms = 5;
        item2->Bathrooms = 3.5;
        item1->MonthlyRent = 2550.75;
    
        Console::WriteLine(L"-=- Sample Property -=-");
        Console::WriteLine(L"Property #:    {0}",
    			item2->PropertyCode);
        Console::WriteLine(L"Property Type: {0}",
    			item2->PropertyType);
        Console::WriteLine(L"Condition:     {0}",
    			item2->PropertyCondition);
        Console::WriteLine(L"Bedrooms:      {0}",
    			item2->Bedrooms);
        Console::WriteLine(L"Bathrooms:     {0}",
    			item2->Bathrooms);
        Console::WriteLine(L"Monthly Rent:  {0}",
    			item2->MonthlyRent);
    
        Console::WriteLine(L"-------------------------------------------");
        if( properties->Contains(item2) == true )
    Console::WriteLine("That property already exists in the listing");
        else
    Console::WriteLine("The property was not found in our database");
        Console::WriteLine(L"8--8--8--8--8--8--8--8--8--8--8--8--8--8--8");
    
        return 0;
    }
  6. Execute the application to see the result: 
    <+> Solas Properties Rental <+>
    <->   Properties Listing    <->
    ---------------------------
    1. Property Details
    Property #:    737495
    Property Type: Apartment
    Condition:     Good
    Bedrooms:      1
    Bathrooms:     1
    Monthly Rent:  950
    ---------------------------
    2. Property Details
    Property #:    293749
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  2550.75
    ---------------------------
    3. Property Details
    Property #:    224006
    Property Type: Apartment
    Condition:     Excellent
    Bedrooms:      2
    Bathrooms:     1
    Monthly Rent:  1250.55
    ---------------------------
    4. Property Details
    Property #:    197249
    Property Type: Townhouse
    Condition:     BadShape
    Bedrooms:      4
    Bathrooms:     2.5
    Monthly Rent:  1750.65
    ---------------------------
    5. Property Details
    Property #:    592795
    Property Type: SingleFamily
    Condition:     Good
    Bedrooms:      3
    Bathrooms:     2
    Monthly Rent:  1870.35
    ================================
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    -=- Sample Property -=-
    Property #:    293749
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  2550.75
    -------------------------------------------
    That property already exists in the listing
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    -=- Sample Property -=-
    Property #:    290004
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  0
    -------------------------------------------
    The property was not found in our database
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    Press any key to continue . . .
  7. Close the DOS window

Getting the Index of an Item

The Contains method is used to check whether a particular item (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 item to look for in the list. If the item is found in the collection, the method returns its index. If there is no item defined like that, the method returns -1. Here is an example of implementing this method:

using namespace System;
using namespace System::Collections;

public ref class CObjects : public IList
{
private:
    int items;
    array<Object ^> ^ objects;

public:

    . . . No Change

    virtual int IndexOf(Object ^);
};

. . . No Change

int CObjects::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 (in our example, that would be the objects array) to find out whether the item 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.

Practical Learning Practical Learning: Getting the Index of an Item

  1. Open the Properties.cpp source file.
    In the Functions combo box, select IndexOf and implement the method as follows:
     
    // This method is used to check whether the item passed as 
    // argument exists in the collection. If so, it returns its index
    int CProperties::IndexOf(Object ^ value)
    {
        int custIndex = -1;
    
        for(int i = 0; i < Count; i++)
        {
    	if( dynamic_cast<CRentalProperty ^>(
    	  this[i])->Equals(dynamic_cast<CRentalProperty ^>(value)) )
    	{
    	    custIndex = i;
    	    break;
    	}
        }
    
        return custIndex;
    }
  2. Open the Exercise.cpp source file and make the following changes:
     
    #include "RentalProperty.h"
    #include "Properties.h"
    
    using namespace System;
    
    int main()
    {
        . . . No Change
        Console::WriteLine(L"8--8--8--8--8--8--8--8--8--8--8--8--8--8--8");
    
        CRentalProperty ^ item3 = gcnew CRentalProperty;
        item3->PropertyCode = 224006;
        item3->PropertyType = PropertyTypes::Apartment;
        item3->PropertyCondition = PropertyConditions::Excellent;
        item3->Bedrooms = 2;
        item3->Bathrooms = 1;
        item3->MonthlyRent = 1250.55;
    
        Console::WriteLine(L"-=- Sample Property -=-");
        Console::WriteLine(L"Property #:    {0}",
    			item3->PropertyCode);
        Console::WriteLine(L"Property Type: {0}",
    			item3->PropertyType);
        Console::WriteLine(L"Condition:     {0}",
    			item3->PropertyCondition);
        Console::WriteLine(L"Bedrooms:      {0}",
    			item3->Bedrooms);
        Console::WriteLine(L"Bathrooms:     {0}",
    			item3->Bathrooms);
        Console::WriteLine(L"Monthly Rent:  {0}",
    			item3->MonthlyRent);
        Console::WriteLine(L"The index of this property is: {0}",
        properties->IndexOf(item3));
        Console::WriteLine(L"8--8--8--8--8--8--8--8--8--8--8--8--8--8--8");
        return 0;
    }
  3. Execute the application to see the result: 
    <+> Solas Properties Rental <+>
    <->   Properties Listing    <->
    ---------------------------
    1. Property Details
    Property #:    737495
    Property Type: Apartment
    Condition:     Good
    Bedrooms:      1
    Bathrooms:     1
    Monthly Rent:  950
    ---------------------------
    2. Property Details
    Property #:    293749
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  2550.75
    ---------------------------
    3. Property Details
    Property #:    224006
    Property Type: Apartment
    Condition:     Excellent
    Bedrooms:      2
    Bathrooms:     1
    Monthly Rent:  1250.55
    ---------------------------
    4. Property Details
    Property #:    197249
    Property Type: Townhouse
    Condition:     BadShape
    Bedrooms:      4
    Bathrooms:     2.5
    Monthly Rent:  1750.65
    ---------------------------
    5. Property Details
    Property #:    592795
    Property Type: SingleFamily
    Condition:     Good
    Bedrooms:      3
    Bathrooms:     2
    Monthly Rent:  1870.35
    ================================
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    -=- Sample Property -=-
    Property #:    293749
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  2550.75
    -------------------------------------------
    That property already exists in the listing
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    -=- Sample Property -=-
    Property #:    290004
    Property Type: SingleFamily
    Condition:     Excellent
    Bedrooms:      5
    Bathrooms:     3.5
    Monthly Rent:  0
    -------------------------------------------
    The property was not found in our database
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    -=- Sample Property -=-
    Property #:    224006
    Property Type: Apartment
    Condition:     Excellent
    Bedrooms:      2
    Bathrooms:     1
    Monthly Rent:  1250.55
    The index of this property is: 2
    8--8--8--8--8--8--8--8--8--8--8--8--8--8--8
    Press any key to continue . . .
  4. Close the DOS window
 

Previous Copyright © 2007-2013, FunctionX Next