Home

Classes and Indexed Properties

 

Read/Write Indexed Properties

As done for a primitive type, you can allow the clients of your indexed property to assign values to the array's elements. Once again, when defining the property, you should include a set accessor to it. You must pass two parameters to the set accessor. The first parameter is used to identify the index of the array element that will receive the value. The second parameter holds the value that will be assigned to the element of the indexed property. Here is an example:

public ref class CSchoolRegistration
{
    array<CStudent ^> ^  std;

public:
    property CStudent ^ default[int]
    {
        CStudent ^ get(int i) { return std[i]; }
        void set(int i, CStudent ^ value) { std[i] = value; }
    }

    CSchoolRegistration()
    {
	std = gcnew array<CStudent ^>(5);
    }
};

After doing this, you can create an element of the array by applying the square brackets to the instance of the class and assigning the desired value to it. The problem with the class is that, since it may have many member variables (or properties), to completely define each element, you must provide a value to the member variables of the class itself. Here is an example:

using namespace System;

public ref class CStudent
{
public:
    long StudentID;
    String ^ FirstName;
    String ^ LastName;
    String ^ Gender;

    virtual String ^ ToString() override
    {
        String ^ str = L"Student ID: " + StudentID +
                       L"\nFirst Name: " + FirstName +
                       L"\nLast Name:  " + LastName +
                       L"\nGender:     " + Gender;
        return str;
    }
};

public ref class CSchoolRegistration
{
    array<CStudent ^> ^ std;

public:
    property CStudent ^ default[int]
    {
        CStudent ^ get(int i) { return std[i]; }
        void set(int i, CStudent ^ value)
	{
	    std[i] = value;
	}
    }

    CSchoolRegistration()
    {
	std = gcnew array<CStudent ^>(5);
    }
};

int main()
{
    CSchoolRegistration ^ registration = gcnew CSchoolRegistration;

    CStudent ^ stud = gcnew CStudent;
    stud->StudentID = 604057;
    stud->FirstName = L"Gertrude";
    stud->LastName  = L"Monayong";
    stud->Gender    = L"Female";
        
    registration[2] = stud;

    Console::WriteLine(L"Student Information");
    Console::WriteLine(L"---------------------");
    Console::WriteLine(L"First Name: {0}", registration[2]->FirstName);
    Console::WriteLine(L"Last Name:  {0}", registration[2]->LastName);
    Console::WriteLine(L"Gender:     {0}\n", registration[2]->Gender);
         
    return 0;
}

This would produce:

Student Information
---------------------
First Name: Gertrude
Last Name:  Monayong
Gender:     Female

Press any key to continue . . .

Practical Learning: Using an Indexed Property

  1. To combine some of the topics we have studied so far, we will create a serializable list of rental properties in a file based database application.
    To create a new application, on the main menu, click File -> New -> Project...
  2. In the Templates list, click CLR Empty Project.
    Set the Name to SolasPropertRental1 and click OK
  3. To create a new class, in the Solution Explorer, right-click SolasPropertyRental1 -> Add -> Class...
  4. In the Templates list, click C++ Class and click Add
  5. Set the Name to CRentalProperty and click Finish
  6. Implement the header file as follows:
     
    #pragma once
    
    using namespace System;
    
    [Serializable]
    public ref class CRentalProperty
    {
    private:
        // These are the characteristics of a property
        long     propCode;
        String ^ type;
        String ^ cond;
        short    beds;
        double   baths;
        double   val;
    
    public:
        property long PropertyCode
        {
            long get() { return propCode; }
            void set(long value) { propCode = value; }
        }
    
        property String ^ PropertyType
        {
            String ^ get() { return type; }
            void set(String ^ value) { type = value; }
        }
    
        property String ^ PropertyCondition
        {
            String ^ get() { return cond; }
            void set(String ^ value) { cond = value; }
        }
    
        property short Bedrooms
        {
            short get() { return beds; }
            void set(short value) { beds = value; }
        }
    
        property double Bathrooms
        {
            double get() { return (baths <= 0) ? 0.00 : baths; }
            void set(double value) { baths = value; }
        }
    
        property double MonthlyRent
        {
            double get() { return (val <= 0) ? 0.00 : val; }
            void set(double value) { val = value; }
        }
    
        // This flag is used to specify whether a property 
        // still holds the default values or it has 
        // previously been updated
        int CreationFlag;
    
    public:
        // This constructor is used to create 
        // default values for a property
        CRentalProperty(void);
        virtual String ^ ToString() override;
    };
  7. Access the RentalProperty.cpp source file and change it as follows:
     
    #include "RentalProperty.h"
    
    CRentalProperty::CRentalProperty(void)
    {
        Random ^ rnd = gcnew Random();
        propCode     = rnd->Next(100000, 999999);
    	type         = L"Unknown";
        cond         = L"Unknown";
        beds         = 0;
        baths        = 0.0;
        val          = 0.00;
    	CreationFlag = 0;
    }
    
    // This method is used to create a string that
    // the characteristics of a property
    String ^ CRentalProperty::ToString()
    {
        return L"Property #:   " + PropertyCode +
               L"\nType:         " + PropertyType +
               L"\nCondition:    " + PropertyCondition +
               L"\nBedrooms:     " + Bedrooms +
               L"\nBathrooms:    " + Bathrooms +
               L"\nMonthly Rent: " + MonthlyRent.ToString("C");
    }
  8. To create a new class, in the Class View, right-click SolasPropertyRental1 -> Add -> Class...
  9. In the Templates list, click C++ Class and click Add
  10. Set the Name to CPropertyListing and click Finish
  11. Change the header file as follows:
     
    #pragma once
    
    #include "RentalProperty.h"
    
    using namespace System::IO;
    using namespace System::Runtime::Serialization;
    using namespace System::Runtime::Serialization::Formatters::Binary;
    
    public ref class CPropertyListing
    {
    public:
        array<CRentalProperty ^> ^ props;
    
        property CRentalProperty ^ default[int]
        {
            CRentalProperty ^ get(int i)
            {
                if( (i >= 0) && (i < 100) )
                    return props[i];
                else
    		return nullptr;
            }
    
    	void set(int i, CRentalProperty ^ value)
    	{
    	    props[i] = value;
    	}
        }
    
    public:
    	CPropertyListing(void);
    };
  12. In the Class View, right-click CPropertyListing -> Add -> Function...
  13. Set the Return Type to void
    Set the Function Name to SaveProperties
    Click Finish and implement the method as follows:
     
    void CPropertyListing::SaveProperties()
    {
        String ^ strFilename = L"Properties.prp";
        FileStream ^ fstProperties = gcnew FileStream(strFilename, 
    						  FileMode::Create);
        BinaryFormatter ^ bfmProperties = gcnew BinaryFormatter;
    
        try {
    	bfmProperties->Serialize(fstProperties, this->props);
        }
        catch(ArgumentNullException ^)
        {
    	Console::WriteLine(L"The properties listing is not available");
        }
        catch(SerializationException ^)
        {
    	Console::WriteLine(L"The listing could not be saved");
        }
        finally {
    	fstProperties->Close();
        }
    }
  14. In the Class View, right-click CPropertyListing -> Add -> Function...
  15. Set the Return Type to void
    Set the Function Name to CreateDefaultListing
    Click Finish and implement the method as follows:
     
    void CPropertyListing::CreateDefaultListing(void)
    {
        Random ^ rndNumber = gcnew Random;
    
        for(int i = 0; i < 100; i++)
        {
    	CRentalProperty ^ rental = gcnew CRentalProperty;
    	rental->PropertyCode = rndNumber->Next(100000, 999999);
    	rental->PropertyType = L"Unknown";
    	rental->PropertyCondition = L"Unknown";
    	rental->Bedrooms = 0;
    	rental->Bathrooms = 0;
    	rental->MonthlyRent = 0.00;
    	rental->CreationFlag = 0;
    	props[i] = rental;
        }
    
        SaveProperties();
    }
  16. In the Class View, right-click CPropertyListing -> Add -> Function...
  17. Set the Return Type to void
    Set the Function Name to OpenProperties
    Click Finish and implement the method as follows:
     
    void CPropertyListing::OpenProperties(void)
    {
        String ^ strFilename = L"Properties.prp";
        FileStream ^ fstProperties = nullptr;
        BinaryFormatter ^ bfmProperties = nullptr;
    
        // If the list of properties had already been created
        // then open it
        if( File::Exists(strFilename) )
        {
    	try {
    	    fstProperties = gcnew FileStream(strFilename,
    					     FileMode::Open);
    	    bfmProperties = gcnew BinaryFormatter;
    	    this->props = 
    		dynamic_cast<array<CRentalProperty ^>^>(
    			bfmProperties->Deserialize(fstProperties));
    	}
    	catch(ArgumentNullException ^)
    	{
    	    Console::WriteLine(
    		L"The properties listing is not available");
    	}
    	catch(SerializationException ^)
    	{
    	    Console::WriteLine(L"The listing could not be opened");
    	}
    	finally
    	{
    	    fstProperties->Close();
    	}
        }
        else
    	return;
    }
  18. In the Class View, right-click CPropertyListing -> Add -> Function...
  19. Set the Return Type to void
    Set the Function Name to ShowProperties
    Click Finish and implement the method as follows:
     
    void CPropertyListing::ShowProperties(void)
    {
        OpenProperties();
    
        Console::WriteLine(L"Here is a list of our properties");
        for(int i = 0; i < 26; i++)
        {
            Console::WriteLine(L"{0}.----------------------------------",
    			i + 1);
            Console::WriteLine(props[i]);
        }
        Console::WriteLine(L"======================================");
    }
  20. In the Class View, right-click CPropertyListing -> Add -> Function...
  21. Set the Return Type to void
    Set the Function Name to CreateProperty
    Click Finish and implement the method as follows:
     
    void CPropertyListing::CreateProperty(void)
    {
        CRentalProperty ^ prop = gcnew CRentalProperty;
    
        for(int i = 0; i < 100; i++)
        {
    	if( props[i]->CreationFlag == 0 )
    	{
    	    try {
    		Console::WriteLine(L"New Property Entry");
    		Console::WriteLine(L"Property Types");
    		Console::WriteLine(L"1 - Single Family");
    		Console::WriteLine(L"2 - Townhouse");
    		Console::WriteLine(L"3 - Apartment");
    		Console::Write(L"Enter your choice(1, 2, or 3): ");
    		int type = int::Parse(Console::ReadLine());
    
    		if( type == 1 )
    		    props[i]->PropertyType = L"Single Family";
    		else if( type == 2 )
    		    props[i]->PropertyType = L"Townhouse";
    		else if( type == 3 )
    		    props[i]->PropertyType = L"Apartment";
    		else
    		    props[i]->PropertyType = L"Unknown";
    	    }
    	    catch(FormatException ^)
    	    {
    		Console::WriteLine(L"Invalid Choice");
    	    }
    
    	    try {
    		Console::WriteLine(L"Property Conditions");
    		Console::WriteLine(L"1 - Excellent");
    		Console::WriteLine(L"2 - Good");
    		Console::WriteLine(L"3 - Bad Shape");
    		Console::Write(L"Enter your choice(1, 2, or 3): ");
    		int cond = int::Parse(Console::ReadLine());
    
    		if( cond == 1 )
    		    props[i]->PropertyCondition = L"Excellent";
    		else if( cond == 2 )
    		    props[i]->PropertyCondition = L"Good";
    		else if( cond == 3 )
    		    props[i]->PropertyCondition = L"Bad Shape";
    		else
    		    props[i]->PropertyCondition = L"Unknown";
    	    }
    	    catch(FormatException ^)
    	    {
    		Console::WriteLine(L"Invalid Selection");
    	    }
    
    	    try {
    		Console::Write(L"How many bedrooms? ");
    		props[i]->Bedrooms = 
    			short::Parse(Console::ReadLine());
    	    }
    	    catch(FormatException ^)
    	    {
    		Console::WriteLine("Invalid Value");
    	    }
    
    	    try {
    		Console::Write(L"How many bathrooms? ");
    		props[i]->Bathrooms = 
    			double::Parse(Console::ReadLine());
    	    }
    	    catch(FormatException ^)
    	    {
    		Console::WriteLine("Invalid Value");
    	    }
    
    	    try {
    		Console::Write(L"Monthly Rent: ");
    		props[i]->MonthlyRent = 
    			double::Parse(Console::ReadLine());
    	    }
    	    catch(FormatException ^)
    	    {
    		Console::WriteLine("Unrecognizable Value");
    	    }
    
    	    props[i]->CreationFlag = 1;
    	    SaveProperties();
    
    	    return;
    	}
        }
    
        Console::WriteLine(L"You cannot create a new property."
    	        L"You can only modify or replace an existing one.");
    }
  22. In the Class View, right-click CPropertyListing -> Add -> Function...
  23. Set the Return Type to void
    Set the Function Name to ShowProperty
    Click Finish and implement the method as follows:
     
    void CPropertyListing::ShowProperty(void)
    {
        try {
    	OpenProperties();
    
    	Console::WriteLine(
    		L"Here is a list of our properties by code");
    	for (int i = 0; i < 26; i++)
    	    Console::WriteLine(L"Property Code: {0}",
               		props[i]->PropertyCode);
    
    	Console::Write(L"Enter Property Code: ");
    	long code = long::Parse(Console::ReadLine());
    
    	for(int i = 0; i < 100; i++)
    	{
    	    if( props[i]->PropertyCode == code )
    	    {
    		Console::WriteLine(
    			L"======================================");
    		Console::WriteLine(L"Property Information");
    		Console::WriteLine(
    			L"--------------------------------------");
    		Console::WriteLine(props[i]);
    		Console::WriteLine(
    			L"======================================");
    	    }
    	}
        }
        catch(FormatException ^)
        {
            Console::WriteLine(L"=- Invalid Property Code -=");
        }
    }
  24. Scroll up the PropertyListing.cpp source file and change the constructor as follows:
     
    #include "PropertyListing.h"
    
    CPropertyListing::CPropertyListing(void)
    {
        props = gcnew array<CRentalProperty ^>(100);
    
        // Check if the default list of properties has never been created.
        // If there is no default list of properties,
        // Then create it and save the file
        if( !File::Exists(L"Properties.prp") )
        {
    	CreateDefaultListing();
        }
    
        // Since we have a file that holds the list of properties
        // open it and store the properties in our array
        OpenProperties();
    }
  25. To create a new source file, on the main menu, click Project -> Add New Item...
  26. In the Templates list, click C++ File (.cpp)
  27. Set the Name to Exercise and press Enter
  28. Implement the file as follows:
     
    using namespace System;
    
    #include "PropertyListing.h"
    
    int main()
    {
        CPropertyListing ^ properties = gcnew CPropertyListing();
        int choice = 0;
    
        do {
    	try {
    	   Console::WriteLine(L"==================================");
    	    Console::WriteLine(L"What do you want to do?");
    	    Console::WriteLine(L"1. Create a new property");
    	    Console::WriteLine(L"2. See one particular property");
    	    Console::WriteLine(L"3. Show the properties");
    	    Console::WriteLine(L"0. Quit");
    	    Console::Write(L"Your Choice? ");
    	    choice = int::Parse(Console::ReadLine());
    	   Console::WriteLine(L"----------------------------------");
    
    	    if( choice == 1 )
    		properties->CreateProperty();
    	    else if( choice == 2 )
    		properties->ShowProperty();
    	    else if( choice == 3 )
    		properties->ShowProperties();
    	}
    	catch(FormatException ^)
    	{
    	    Console::WriteLine(L"Invalide Choice");
    	}
        }while( (choice > 0) && (choice < 4) );
    
        return 0;
    }
  29. Execute the application to test it
 

Previous Copyright © 2007-2012 FunctionX Home