Home

Topics on Indexed Properties and Classes

 

A Class as Index

As opposed to returning a class, an indexed property can use a class as its index. When creating such a property, the primary action you must take is to include a class and its name as a parameter to the default property. You can start such a class as follows:

public ref class CStudent
{
};

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

public:
    property String ^ default[CStudent ^]
    {
    }

    CSchoolRegistration()
    {
        students = gcnew array<CStudent ^>(50);
    }
};

When implementing the class, you should proceed the same way we have done so far following the rules of a method that takes an argument and returns a value other than void. Here is an example:

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

public:
    property String ^ default[CStudent ^]
    {
        String ^ get(CStudent ^ std)
        {
            for (int i = 0; i < students->Length; i++)
            {
		String ^ strGender =
			(students[i]->Gender == Female ? L"Female" :
			(students[i]->Gender == Male ? L"Male" : L"Unknown"));
                if (std->StudentID == students[i]->StudentID)
			return L"Student ID: " + 
				students[i]->StudentID.ToString() +
 		 	       L"\nFirst Name: " + students[i]->FirstName +
                               L"\nLast Name:  " + students[i]->LastName +
                               L"\nGender:     " + strGender;
            }

            // Unknown student or the number was not found
            return L"Unknown";
        }
    }

    CSchoolRegistration()
    {
        students = gcnew array<CStudent ^>(50);
    }
};

After creating the property, you can use it. To do this, you must pass an object that is the type of the index. You can then use the returned value as you see fit. Here is an example:

using namespace System;

public enum Classification
{
    Female,
    Male,
    Unknown
};

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

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

public:
    property String ^ default[CStudent ^]
    {
        String ^ get(CStudent ^ std)
        {
            for (int i = 0; i < students->Length; i++)
            {
		String ^ strGender =
			(students[i]->Gender == Female ? L"Female" :
			(students[i]->Gender == Male ? L"Male" : L"Unknown"));
                if (std->StudentID == students[i]->StudentID)
			return L"Student ID: " + 
				students[i]->StudentID.ToString() +
	 	 	       L"\nFirst Name: " + students[i]->FirstName +
                               L"\nLast Name:  " + students[i]->LastName +
                               L"\nGender:     " + strGender;
            }

            // Unknown student or the number was not found
            return L"Unknown";
        }
    }

    CSchoolRegistration()
    {
        students = gcnew array<CStudent ^>(50);

        students[0] = gcnew CStudent();
        students[0]->StudentID = 917294;
        students[0]->FirstName = L"Helene";
        students[0]->LastName = L"Mukoko";
        students[0]->Gender = Female;

        students[1] = gcnew CStudent();
        students[1]->StudentID = 283764;
        students[1]->FirstName = L"Patrice";
        students[1]->LastName = L"Katts";
        students[1]->Gender = Unknown;

        students[2] = gcnew CStudent();
        students[2]->StudentID = 192046;
        students[2]->FirstName = L"Armand";
        students[2]->LastName = L"Essono";
        students[2]->Gender = Male;

        students[3] = gcnew CStudent();
        students[3]->StudentID = 618268;
        students[3]->FirstName = L"Bertrand";
        students[3]->LastName = L"Yamaguchi";
        students[3]->Gender = Male;

        students[4] = gcnew CStudent();
        students[4]->StudentID = 820648;
        students[4]->FirstName = L"Hortense";
        students[4]->LastName = L"McNeal";
        students[4]->Gender = Female;

        students[5] = gcnew CStudent();
        students[5]->StudentID  = 917394;
        students[5]->FirstName = L"Alfredo";
        students[5]->LastName = L"Olmos";
        students[5]->Gender = Unknown;

        students[6] = gcnew CStudent();
        students[6]->StudentID  = 163864;
        students[6]->FirstName = L"Josiane";
        students[6]->LastName = L"Euler";
        students[6]->Gender = Female;

        students[7] = gcnew CStudent();
        students[7]->StudentID  = 826384;
        students[7]->FirstName = L"Joan";
        students[7]->LastName = L"Jones";
        students[7]->Gender =  Female ;
    }
};

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

    CStudent ^ pupil = gcnew CStudent;
    pupil->StudentID = 820648;

    String ^ strStudent = pupils[pupil];

    Console::WriteLine(L"=====================");
    Console::WriteLine(L"Student Information");
    Console::WriteLine(L"---------------------");
    Console::WriteLine(strStudent);

    pupil->StudentID = 192046;
    strStudent = pupils[pupil];

    Console::WriteLine(L"=====================");
    Console::WriteLine(L"Student Information");
    Console::WriteLine(L"---------------------");
    Console::WriteLine(strStudent);

    Console::WriteLine(L"=====================\n");
    return 0;
}

This would produce:

=====================
Student Information
---------------------
Student ID: 820648
First Name: Hortense
Last Name:  McNeal
Gender:     Female
=====================
Student Information
---------------------
Student ID: 192046
First Name: Armand
Last Name:  Essono
Gender:     Male
=====================

Press any key to continue . . .

You can also directly pass an instance of the class in the square brackets of the object that holds the indexed property, as long as you specify the object. Here is an example:

public ref class CStudent
{
public:
    ... No Change
	
    CStudent()
    {
    }

    CStudent(long id)
    {
        this->StudentID = id;
    }
};

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

public:
    property String ^ default[CStudent ^]
    {
        ... No Change
    }

    CSchoolRegistration()
    {
        students = gcnew array<CStudent ^>(50);

        ... No Change
    }
};

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

    String ^ strStudent = pupils[gcnew CStudent(826384)];
    Console::WriteLine(L"=====================");
    Console::WriteLine(L"Student Information");
    Console::WriteLine(L"---------------------");
    Console::WriteLine(strStudent);

    strStudent = pupils[gcnew CStudent(917394)];

    Console::WriteLine(L"=====================");
    Console::WriteLine(L"Student Information");
    Console::WriteLine(L"---------------------");
    Console::WriteLine(strStudent);

    Console::WriteLine(L"=====================\n");
    return 0;
}

This would produce:

=====================
Student Information
---------------------
Student ID: 826384
First Name: Joan
Last Name:  Jones
Gender:     Female
=====================
Student Information
---------------------
Student ID: 917394
First Name: Alfredo
Last Name:  Olmos
Gender:     Unknown
=====================

Press any key to continue . . .

Overloading a Class-Based Indexed Property

As mentioned for indexed properties that return primitive types, you can overload an indexed property that produces a class. You do this following the same rules applied to method overloading and arrays:

  • If two indexed properties take only one parameter, each must take a different type of parameter than the other. The parameter can be a primitive type or a class. Here are examples:
     
    using namespace System;
    
    public enum Classification
    {
        Female,
        Male,
        Unknown
    };
    
    public ref class CMajor
    {
    public:
        String ^ Name;
        int CreditsRequired;
    };
    
    public ref class CStudent
    {
    public:
    	long StudentNumber;
        String ^ FullName;
        Classification Gender;
    
        virtual String ^ ToString() override
        {
    	String ^ strGender =
    		(Gender == Female ? L"Female" :
    			(Gender == Male ? L"Male" : L"Unknown"));
    
    	String ^ str = L"Student #:     " +
    	             StudentNumber.ToString() +
                         L"\nFull Name:     " + FullName +
                         L"\nGender:        " + strGender;
            return str;
        }
    };
    
    public ref class CStudentRegistration
    {
    private:
    	array<CStudent ^> ^ std;
    
    public:
    	CStudentRegistration()
        {
    		std = gcnew array<CStudent ^>(5);
    
            std[0] = gcnew CStudent;
            std[0]->StudentNumber = 304850;
            std[0]->FullName = L"Helene Mukoko";
            std[0]->Gender = Female;
    
            std[1] = gcnew CStudent;
            std[1]->StudentNumber = 926304;
            std[1]->FullName = L"Patrice Katts";
            std[1]->Gender = Unknown;
    
            std[2] = gcnew CStudent;
            std[2]->StudentNumber = 330647;
            std[2]->FullName = L"Armand Essono";
            std[2]->Gender = Male;
    
            std[3] = gcnew CStudent;
            std[3]->StudentNumber = 631846;
            std[3]->FullName = L"Bertrand Yamaguchi";
            std[3]->Gender = Male;
    
            std[4] = gcnew CStudent;
            std[4]->StudentNumber = 209374;
            std[4]->FullName = L"Anselme Bongos";
            std[4]->Gender = Male;
        }
    
        // This property takes a string and produces a Student object
        property CStudent ^ default[String ^]
        {
            CStudent ^ get(String ^ strFullName)
            {
                for (int i = 0; i < std->Length; i++)
                {
                    if (std[i]->FullName == strFullName)
                        return std[i];
                }
                return nullptr;
            }
        }
    
        // This property takes a number and produces a Student object
        property CStudent ^ default[long]
        {
            CStudent ^ get(long nbr)
            {
                for (int i = 0; i < std->Length; i++)
                {
                    if( nbr == std[i]->StudentNumber )
                        return std[i];
                }
                return nullptr;
            }
        }
    
        // This property takes a major produces its definition
        property String ^ default[CMajor ^]
        {
            String ^ get(CMajor ^ maj)
            {
                return "Major: " + maj->Name +
                       " - " + maj->CreditsRequired +
                       " Credits Required";
            }
        } 
    };
    
    int main()
    {
        CStudentRegistration ^ pupils = gcnew CStudentRegistration();
    
        CMajor ^ m1 = gcnew CMajor;
        m1->Name = L"Computer Sciences";
        m1->CreditsRequired = 120;
    
        CMajor ^ m2 = gcnew CMajor;
        m2->Name = L"Informtation Technology";
        m2->CreditsRequired = 120;
    
        Console::WriteLine(L"=-= Student Identification =-=");
        Console::WriteLine(pupils["Helene Mukoko"]);
        Console::WriteLine(pupils[m1]);
        Console::WriteLine(L"--------------------------------------------------");
    
        Console::WriteLine(L"=-= Student Identification =-=");
        Console::WriteLine(pupils[330647]);
        Console::WriteLine(pupils[m2]);
        Console::WriteLine(L"--------------------------------------------------");
        Console::WriteLine();
    
        return 0;
    }
    This would produce:
    =-= Student Identification =-=
    Student #:     304850
    Full Name:     Helene Mukoko
    Gender:        Female
    Major: Computer Sciences - 120 Credits Required
    --------------------------------------------------
    =-= Student Identification =-=
    Student #:     330647
    Full Name:     Armand Essono
    Gender:        Male
    Major: Information Technology - 120 Credits Required
    --------------------------------------------------
    
    Press any key to continue . . .
  • If one property takes only one parameter, the other(s) can take more than one parameter. An indexed property can take different parameters of primitive types as seen in the previous lesson. A property can also take two or more classes as parameters. An indexed property can also take a mix of primitive and class types as parameters.
    Here are examples:
     
    using namespace System;
    
    public enum Classification
    {
        Female,
        Male,
        Unknown
    };
    
    public ref class CStudent
    {
    public:
    	long StudentID;
        String ^ FirstName;
        String ^ LastName;
        Classification Gender;
    
        CStudent()
        {
        }
    
        CStudent(long id)
        {
            this->StudentID = id;
        }
    
        virtual String ^ ToString() override
        {
    	String ^ strGender =
    		(Gender == Female ? L"Female" :
    			(Gender == Male ? L"Male" : L"Unknown"));
    
            return "Student ID:  " + StudentID +
                   "\nFirst Name:  " + FirstName +
                   "\nLast Name:   " + LastName +
                   "\nGender:      " + strGender;
        }
    };
    
    public enum CourseDelivery
    {
        FaceToFace,
        Online,
        Both // Student Choose
    };
    
    public ref class CCourse
    {
    public:
        String ^  ShortName;
        String ^  LongName;
        String ^ Description;
    public:
    	int Credits;
        CourseDelivery DeliveryMode;
    
        CCourse()
        {
        }
    
        CCourse(String ^ name)
        {
            ShortName = name;
        }
    
        virtual String ^ ToString() override
        {
    	String ^ strDeliveryMode =
    		(DeliveryMode == FaceToFace ? L"Face-to-Face" :
    			(DeliveryMode == Online ? L"Online" : L"Both"));
    
            return "Course:      " + ShortName +
                   "\nFull Name:   " + LongName +
                   "\nCredits:     " + Credits +
                   "\nDescription: " + Description +
                   "\nDelivery:    " + strDeliveryMode;
        }
    };
    
    public ref class CSchoolRegistration
    {
        array<CStudent ^> ^ students;
        array<CCourse ^> ^ classes;
    
        // This indexed property takes a student id and 
        // returns the student information
    public:
    	property CStudent ^ default[long]
        {
            CStudent ^ get(long id)
            {
                for (int i = 0; i < students->Length; i++)
                {
                    if (id == students[i]->StudentID)
                        return students[i];
                }
    
                // Unknown student or the number was not found
                return nullptr;
            }
        }
    
        // This indexed property takes a course short name and 
        // it produces a summary of the course information
        property CCourse ^ default[String ^]
        {
            CCourse ^ get(String ^ name)
            {
                for (int i = 0; i < classes->Length; i++)
                {
                    if (name == classes[i]->ShortName)
                        return classes[i];
                }
    
                // Unknown course
                return nullptr;
            }
        }
    
        property String ^ default[CCourse ^, CStudent ^]
        {
            String ^ get(CCourse ^ ToAttend, CStudent ^ registrant)
            {
                // First check that the class exists
                for (int i = 0; i < classes->Length; i++)
                {
                    if (ToAttend->ShortName == classes[i]->ShortName)
                    {
                        // If the class exists, then check if the student exists
                        for (int j = 0; j < students->Length; j++)
                        {
                            if (registrant->StudentID == students[j]->StudentID)
                            {
    	String ^ strDeliveryMode =
    		(classes[i]->DeliveryMode == FaceToFace ? L"Face-to-Face" :
    		(classes[i]->DeliveryMode == Online ? L"Online" : L"Both"));
    
                          return L"Student Identification --\n   Student ID: " +
                                   students[j]->StudentID +
                                 L"\n   Full Name:  " + students[j]->LastName +
                                       L", " + students[j]->FirstName +
                                     L"\nClass to Attend --\n   Course:     " +
                                       classes[i]->ShortName + " - " +
                                       classes[i]->LongName + " (" +
                                       classes[i]->Credits + ")" +
                                       L"\n   Delivery:   " +
                                       strDeliveryMode;
                            }
                        }
                    }
                }
    
                return L"Invalid Registration - You may have to start over";
            }
        }
    
        // This property takes information used to register 
        // a student to a course
        // It also specifies whether the student is willing 
        // to get in the waiting list in case another students drops out
        property String ^ default[CStudent ^, CCourse ^, bool]
        {
            String ^ get(CStudent ^ stud, CCourse ^ Class, bool WaitingList)
            {
                // Check that the student information is valie
                for (int j = 0; j < students->Length; j++)
                {
                    if (stud->StudentID == students[j]->StudentID)
                    {
                        // Now that the student information has been found,
                        // check if the course information is correct
                        for (int i = 0; i < classes->Length; i++)
                        {
                            if (Class->ShortName == classes[i]->ShortName)
                            {
    	String ^ strDeliveryMode =
    	   (classes[i]->DeliveryMode == FaceToFace ? L"Face-to-Face" :
    		(classes[i]->DeliveryMode == Online ? L"Online" : L"Both"));
    
                         // If the class exists, then check if the student exists
                         return L"Student Identification --\n   Student ID: " +
                                       students[j]->StudentID +
                                   L"\n   Full Name:  " + students[j]->LastName +
                                       L", " + students[j]->FirstName +
                                       L"\nClass to Attend --\n   Course:     " +
                                       classes[i]->ShortName + " - " +
                                       classes[i]->LongName + " (" +
                                       classes[i]->Credits + ")" +
                                       L"\n   Delivery:   " +
                                       strDeliveryMode +
                          L"\nStudent is willing to get on the waiting list: " +
    				   + WaitingList;
                            }
                        }
                    }
                }
    
                return L"Invalid Registration - You may have to start over";
            }
        }
    
        CSchoolRegistration()
        {
    	students = gcnew array<CStudent ^>(50);
    	classes = gcnew array<CCourse ^>(3);
    
            students[0] = gcnew CStudent;
            students[0]->StudentID = 917294;
            students[0]->FirstName = L"Helene";
            students[0]->LastName = L"Mukoko";
            students[0]->Gender = Female;
    
            students[1] = gcnew CStudent;
            students[1]->StudentID = 283764;
            students[1]->FirstName = L"Patrice";
            students[1]->LastName = L"Katts";
            students[1]->Gender = Unknown;
    
            students[2] = gcnew CStudent;
            students[2]->StudentID = 192046;
            students[2]->FirstName = L"Armand";
            students[2]->LastName = L"Essono";
            students[2]->Gender = Male;
    
            students[3] = gcnew CStudent;
            students[3]->StudentID = 618268;
            students[3]->FirstName = L"Bertrand";
            students[3]->LastName = L"Yamaguchi";
            students[3]->Gender = Male;
    
            students[4] = gcnew CStudent;
            students[4]->StudentID = 820648;
            students[4]->FirstName = L"Hortense";
            students[4]->LastName = L"McNeal";
            students[4]->Gender = Female;
    
            classes[0] = gcnew CCourse;
            classes[0]->ShortName = L"PHIL140";
            classes[0]->LongName = L"Philosophy - Contemporary Moral Issues";
            classes[0]->Credits = 3;
            classes[0]->Description =
    		L"An exploration of how philosophical analysis can be "
                L"\n\t\ta foundation for thinking clearly about moral issues. "
                  L"\n\t\tProblems analyzed include such widely debated issues "
                    L"\n\t\tas abortion, euthanasia, the death penalty, "
                    L"\n\t\thomosexuality, pornography, reverse discrimination, "
                L"\n\t\tbusiness ethics, sexual equality, and economic equity.";
            classes[1] = gcnew CCourse;
            classes[1]->ShortName = L"MATH140";
            classes[1]->LongName = L"Calculus I";
            classes[1]->Credits = 4;
            classes[1]->Description =
    		L"An introduction to calculus. Topics include functions, "
              L"\n\t\tthe sketching of graphs of functions, limits, continuity, "
              L"\n\t\tderivatives and applications of the derivative, definite "
                L"\n\t\tand indefinite integrals, and calculation of area.";
            classes[2] = gcnew CCourse;
            classes[2]->ShortName = L"ASTR100";
            classes[2]->LongName = L"Introduction to Astronomy";
            classes[2]->Credits = 3;
            classes[2]->Description =
    		L"A discussion of the major areas of astronomy. Topics "
                L"\n\t\tinclude the solar system, stars and stellar evolution, "
                    L"\n\t\tand galaxies. Current topics in astronomy are also "
                    L"\n\t\tdiscussed.";
        }
    };
    
    int main()
    {
        CSchoolRegistration ^ pupils = gcnew CSchoolRegistration;
    
        CStudent ^ std = gcnew CStudent(917294);
        CCourse ^ crs = gcnew CCourse("MATH140"); 
        Console::WriteLine(L"================================================");
        Console::WriteLine(L"Student Registration");
        Console::WriteLine(L"------------------------------------------");
        Console::WriteLine(pupils[crs, std]);
    
        std = gcnew CStudent(820648);
        crs = gcnew CCourse("PHIL140");
        Console::WriteLine(L"================================================");
        Console::WriteLine(L"Student Registration");
        Console::WriteLine(L"------------------------------------------");
        Console::WriteLine(pupils[std, crs, true]);
    
        Console::WriteLine(
    	L"================================================\n");
        return 0;
    }
    This would produce:
    ================================================
    Student Registration
    ------------------------------------------
    Student Identification --
       Student ID: 917294
       Full Name:  Mukoko, Helene
    Class to Attend --
       Course:     MATH140 - Calculus I (4)
       Delivery:   Face-to-Face
    ================================================
    Student Registration
    ------------------------------------------
    Student Identification --
       Student ID: 820648
       Full Name:  McNeal, Hortense
    Class to Attend --
       Course:     PHIL140 - Philosophy - Contemporary Moral Issues (3)
       Delivery:   Face-to-Face
    Student is willing to get on the waiting list: True
    ================================================
    
    Press any key to continue . . .

Practical Learning: Overloading an Indexed Property

  1. To overload the indexed property, access the PropertyListing.h header file and change it as follows:
     
    #pragma once
    
    #include "RentalProperty.h"
    
    public ref class CPropertyListing
    {
    public:
        array<CRentalProperty ^> ^ props;
    
        property CRentalProperty ^ default[int]
        {
            CRentalProperty ^ get(int i)
            {
                    if ((i >= 0) && (i < 40))
                        return props[i];
                    else return nullptr;
            }
        }
    
        property CRentalProperty ^ default[long]
        {
            CRentalProperty ^ get(long code)
            {
                for (int i = 0; i < props->Length; i++)
                        if (code == props[i]->PropertyCode)
                        return props[i];
                return nullptr;
            }
        }
    
    public:
    	CPropertyListing(void);
    };
  2. Access the Exercise.cpp source file and change it as follows:
     
    using namespace System;
    
    #include "PropertyListing.h"
    
    int main()
    {
        CPropertyListing ^ properties = gcnew CPropertyListing();
        long lngCode;
    
        Console::WriteLine(L"Here is a list of our properties by code");
        for(int i = 0; i < 6; i++)
            Console::WriteLine(L"Property Code: {0}",
    			properties->props[i]->PropertyCode);
    
        try {
    	Console::Write("Enter Property Code: ");
    	lngCode = long::Parse(Console::ReadLine());
    
            Console::WriteLine(L"======================================");
            Console::WriteLine(L"Property Information");
            Console::WriteLine(L"--------------------------------------");
            Console::WriteLine(properties[lngCode]);
            Console::WriteLine(L"======================================");
        }
        catch(FormatException ^)
        {
            Console::WriteLine(L"=- Invalid Property Code -=");
        }
    
        return 0;
    }
  3. Press Ctrl + F5 to execute the application 
  4. Close the DOS window
 

Previous Copyright © 2007-2013, FunctionX Next