|
Classes and Indexed Properties
|
|
Fundamentals of Indexed Properties and Classes
|
|
We learned to create and use indexed properties
that were taking parameters of primitive types. Just as we did with primitive
types, you can create an indexed property that is of a class type. For example, you can create a class so that
one of the its member variables declared as an array can be accessed with an index
directly applied to an instance of the class.
Practical
Learning: Introducing Indexers and Classes |
|
- Start Microsoft Visual C++ 2005 or Microsoft Visual C++ 2005 Express
Edition
- To start a new project, on the main menu, click File -> New ->
Project...
- In the Project Types, make sure Visual C++ is selected.
In the Templates list, click CLR Empty Project
- Set the name to PropertyRental2 and click OK
- To create a new class, on the main menu, click Project -> Add Class...
- In the Templates list, click C++ Class and click Acc
- Set the Name to CRentalProperty and click Finish
- Change the header file as follows:
#pragma once
using namespace System;
public ref class CRentalProperty
{
private:
long propCode;
String ^ cond;
short beds;
double baths;
double val;
public:
property long PropertyCode
{
long get() { return propCode; }
void set(long value) { propCode = 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; }
}
public:
CRentalProperty(void);
virtual String ^ ToString() override;
};
|
- Open the RentalProperty.cpp file and change it as follows:
#include "RentalProperty.h"
CRentalProperty::CRentalProperty(void)
{
Random ^ rnd = gcnew Random();
propCode = rnd->Next(100000, 999999);
cond = L"Unknown";
beds = 0;
baths = 0.0;
val = 0.00;
}
String ^ CRentalProperty::ToString()
{
return L"Property #: " + PropertyCode +
L"\nCondition: " + PropertyCondition +
L"\nBedrooms: " + Bedrooms +
L"\nBathrooms: " + Bathrooms +
L"\nMonthly Rent: " + MonthlyRent.ToString("C");
};
|
- To create a new class, on the main menu, click Project -> Add Class...
- In the Templates list, make sure C++ Class is selected and click Add
- Set the Name to CPropertyListing and press Enter
- Change the header file as follows:
#pragma once
#include "RentalProperty.h"
public ref class CPropertyListing
{
public:
array<CRentalProperty ^> ^ props;
property String ^ default[long]
{
String ^ get(long code)
{
for (int i = 0; i < props->Length; i++)
if (code == props[i]->PropertyCode)
return L"Property #: " +
props[i]->PropertyCode +
L"\nCondition: " +
props[i]->PropertyCondition +
L"\nBedrooms: " +
props[i]->Bedrooms +
L"\nBathrooms: " +
props[i]->Bathrooms +
L"\nMonthly Rent: " +
props[i]->MonthlyRent.ToString("C");
return L"Unidentifiable Property";
}
}
public:
CPropertyListing(void);
};
|
-
Access the PropertyListing.cpp source file and change it as follows:
#include "PropertyListing.h"
CPropertyListing::CPropertyListing(void)
{
Random ^ rnd = gcnew Random;
props = gcnew array<CRentalProperty ^>(40);
// Create a few properties ready to be rented
props[0] = gcnew CRentalProperty;
props[0]->PropertyCode = rnd->Next(100000, 999999);
props[0]->PropertyCondition = L"Excellent";
props[0]->Bedrooms = 5;
props[0]->Bathrooms = 3.5;
props[0]->MonthlyRent = 2650;
props[1] = gcnew CRentalProperty;
props[1]->PropertyCode = rnd->Next(100000, 999999);
props[1]->PropertyCondition = L"Excellent";
props[1]->Bedrooms = 3;
props[1]->Bathrooms = 2.5;
props[1]->MonthlyRent = 1750;
props[2] = gcnew CRentalProperty;
props[2]->PropertyCode = rnd->Next(100000, 999999);
props[2]->PropertyCondition = L"Good";
props[2]->Bedrooms = 4;
props[2]->Bathrooms = 2.5;
props[2]->MonthlyRent = 2450;
props[3] = gcnew CRentalProperty;
props[3]->PropertyCode = rnd->Next(100000, 999999);
props[3]->PropertyCondition = L"Excellent";
props[3]->Bedrooms = 1;
props[3]->Bathrooms = 1.0;
props[3]->MonthlyRent = 880;
props[4] = gcnew CRentalProperty;
props[4]->PropertyCode = rnd->Next(100000, 999999);
props[4]->PropertyCondition = L"Excellent";
props[4]->Bedrooms = 3;
props[4]->Bathrooms = 2.5;
props[4]->MonthlyRent = 1880;
props[5] = gcnew CRentalProperty;
props[5]->PropertyCode = rnd->Next(100000, 999999);
props[5]->PropertyCondition = L"Good";
props[5]->Bedrooms = 2;
props[5]->Bathrooms = 1.0;
props[5]->MonthlyRent = 1050;
// Since we don't yet have a complete list of properties
// Create some empty ones
for (int i = 6; i < 40; i++)
{
props[i] = gcnew CRentalProperty;
}
}
|
- To create a new file, on the main menu, click Project -> Add New
Item...
- In the Templates list, click C++ File (.cpp)
- Set the name to Exercise and click OK
- Implement the file 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;
}
|
- Press Ctrl + F5 to execute the application. Here is an example:
Here is a list of our properties by code
Property Code: 355443
Property Code: 653004
Property Code: 800118
Property Code: 839375
Property Code: 148561
Property Code: 697001
Enter Property Code: 697001
======================================
Property Information
--------------------------------------
Property #: 697001
Condition: Good
Bedrooms: 2
Bathrooms: 1
Monthly Rent: $1,050.00
======================================
Press any key to continue . . .
|
- Close the DOS window
An Integer-Based Indexed Property
|
|
Before designing an indexed property that is class-based,
first create the class that will be used as the data type. The class can be
simple or complex as you judge it necessary. Here is an example of a simple
class:
public ref class CStudent
{
public:
String ^ FirstName;
String ^ LastName;
int Gender;
};
When creating the class that will host the indexed property,
declare an array member variable for the class. Then, create the default property with the
desired accessor(s). Here is an example:
public ref class CStudent
{
public:
String ^ FirstName;
String ^ LastName;
int Gender;
};
public ref class CSchoolRegistration
{
array<CStudent ^> ^ std;
public:
property CStudent ^ default[int]
{
CStudent ^ get(int i) { return std[i]; }
}
CSchoolRegistration()
{
std = gcnew array<CStudent ^>(5);
}
};
After creating the indexing class, you can use it and access
the indexed property; for example, you can retrieve its value(s).
Here is an example:
using namespace System;
public ref class CStudent
{
public:
String ^ FirstName;
String ^ LastName;
int Gender;
};
public ref class CSchoolRegistration
{
array<CStudent ^> ^ std;
public:
property CStudent ^ default[int]
{
CStudent ^ get(int i) { return std[i]; }
}
CSchoolRegistration()
{
std = gcnew array<CStudent ^>(5);
std[0] = gcnew CStudent;
std[0]->FirstName = L"Alfredo";
std[0]->LastName = L"Olmos";
std[0]->Gender = 2;
std[1] = gcnew CStudent;
std[1]->FirstName = L"Patricia";
std[1]->LastName = L"Katts";
std[1]->Gender = 1;
std[2] = gcnew CStudent;
std[2]->FirstName = L"Josiane";
std[2]->LastName = L"Euler";
std[2]->Gender = 1;
std[3] = gcnew CStudent;
std[3]->FirstName = L"Joan";
std[3]->LastName = L"Jones";
std[3]->Gender = 3;
std[4] = gcnew CStudent;
std[4]->FirstName = L"George";
std[4]->LastName = L"Paulson";
std[4]->Gender = 2;
}
};
int main()
{
CSchoolRegistration ^ pupils = gcnew CSchoolRegistration;
for (int i = 0; i < 5; i++)
{
CStudent ^ pupil = pupils[i];
Console::WriteLine(L"Student Information");
Console::WriteLine(L"---------------------");
Console::WriteLine(L"First Name: {0}", pupil->FirstName);
Console::WriteLine(L"Last Name: {0}", pupil->LastName);
Console::WriteLine(L"Gender: {0}\n",
(pupil->Gender == 1 ? "Female" :
(pupil->Gender == 2 ? "Male" : "Unknown")));
}
Console::WriteLine();
return 0;
}
This would produce:
Student Information
---------------------
First Name: Alfredo
Last Name: Olmos
Gender: Male
Student Information
---------------------
First Name: Patricia
Last Name: Katts
Gender: Female
Student Information
---------------------
First Name: Josiane
Last Name: Euler
Gender: Female
Student Information
---------------------
First Name: Joan
Last Name: Jones
Gender: Unknown
Student Information
---------------------
First Name: George
Last Name: Paulson
Gender: Male
Press any key to continue . . .
Practical
Learning: Using an Integer-Based Indexer |
|
- To create an indexed property that takes an integer and returns an object, 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) { return props[i]; }
}
property String ^ default[long]
{
String ^ get(long code)
{
. . . No Change
}
}
public:
CPropertyListing(void);
};
|
- Access the Exercise.cpp source file and change it as follows:
using namespace System;
#include "PropertyListing.h"
int main()
{
CPropertyListing ^ properties = gcnew CPropertyListing;
Console::WriteLine(L"Here is a list of our properties");
for (int i = 0; i < 6; i++)
{
CRentalProperty ^ prop = properties[i];
Console::WriteLine(L"Property Information");
Console::WriteLine(L"--------------------------------------");
Console::WriteLine(L"Property #: {0}", prop->PropertyCode);
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.ToString("C"));
Console::WriteLine(L"======================================");
}
return 0;
}
|
- Press Ctrl + F5 to execute the application
- Close the DOS window
An Indexed Property Using Another Primitive Type
|
|
The above implementation of the CSchoolRegistration class
easily allowed us to locate an element of the array by specifying its
integer-based index. As done for primitive types, an indexed property can take a
parameter other than an integer. In some cases, you may use your class or a class created by
someone else and need to access an element of the array without information
other than its index. Consider the following program:
public ref class CStudent
{
};
public ref class CSchoolRegistration
{
array<CStudent ^> ^ students;
public:
property CStudent ^ default[...]
{
}
CSchoolRegistration()
{
students = gcnew array<CStudent ^>(50);
}
};
Previously, we saw that you could create an indexed property
that took a type other than an integer. For example, we saw that a string
could be used as an index.
By now, we know that a basic indexed property produces (or
all the indexed properties we have studied so far produce) only one value. If
you have a class that has only one member variable, this would be enough. In reality, most
of the time, a class has many member variables. In such a case, when you create an
indexed property
, you need to be able to refer to one exact element of the array. To
make this possible, you must define a way to point to the particular element you
want. One way you can do this is to use one member variable of the class as a reference.
This is better if that member variable holds unique values among the other elements of the
array. For our CStudent class, we could use the StudentID member variable (because we will make sure that each
student has a unique ID). You can start the property as follows:
public ref class CSchoolRegistration
{
public:
property CStudent ^ default[long]
{
}
};
When a user uses this property, he or she must provide a
value that uniquely identifies an element of the array. You in turn, when you
get this value, you can search for it in the array. If you find it and the array
has a get accessor, you can then return the desired but appropriate value. Here
is how this can be done:
public ref class CSchoolRegistration
{
array<CStudent ^> ^ students;
public:
property CStudent ^ default[long]
{
CStudent ^ get(long id)
{
for (int i = 0; i < students->Length; i++)
{
if (students[i]->StudentID == id)
return students[i];
}
// Unknown student or the number was not found
return nullptr;
}
}
CSchoolRegistration()
{
students = gcnew array<CStudent ^>(50);
}
};
After creating the indexed property, you can use it. Once
again, you must follow the rules of a method that takes an argument and returns
a value other than void. In this case, the indexed property must take a string and it
must return a CStudent object. 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;
virtual String ^ ToString() override
{
String ^ str = String::Concat(L"Student ID: ", StudentID.ToString(),
L"\nFirst Name: ", FirstName,
L"\nLast Name: ", LastName,
L"\nGender: ", Gender);
return str;
}
};
public ref class CSchoolRegistration
{
array<CStudent ^> ^ students;
public:
property CStudent ^ default[long]
{
CStudent ^ get(long id)
{
for (int i = 0; i < students->Length; i++)
{
if (students[i]->StudentID == id)
return students[i];
}
// Unknown student or the number was not found
return nullptr;
}
}
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;
}
};
int main()
{
CSchoolRegistration ^ pupils = gcnew CSchoolRegistration;
CStudent ^ pupil = pupils[820648];
Console::WriteLine(L"Student Information");
Console::WriteLine(L"---------------------");
Console::WriteLine(L"First Name: {0}", pupil->FirstName);
Console::WriteLine(L"Last Name: {0}", pupil->LastName);
Console::Write(L"Gender: ");
Console::WriteLine(pupil->Gender);
pupil = pupils[192046];
Console::WriteLine(L"Student Information");
Console::WriteLine(L"---------------------");
Console::WriteLine(L"First Name: {0}", pupil->FirstName);
Console::WriteLine(L"Last Name: {0}", pupil->LastName);
Console::Write(L"Gender: ");
Console::WriteLine(pupil->Gender);
return 0;
}
This would produce:
Student Information
---------------------
First Name: Hortense
Last Name: McNeal
Gender: Female
Student Information
---------------------
First Name: Armand
Last Name: Essono
Gender: Male
Press any key to continue . . .
Topics on Indexed Properties and Classes
|
|
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 |
|
- 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);
};
|
-
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;
}
|
- Press Ctrl + F5 to execute the application
- Close the DOS window
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 |
|
- 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...
- In the Templates list, click CLR Empty Project.
Set the Name to SolasPropertRental1 and click OK
- To create a new class, in the Solution Explorer, right-click
SolasPropertyRental1 -> Add -> Class...
- In the Templates list, click C++ Class and click Add
- Set the Name to CRentalProperty and click Finish
- 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;
};
|
- 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");
}
|
- To create a new class, in the Class View, right-click SolasPropertyRental1
-> Add -> Class...
- In the Templates list, click C++ Class and click Add
- Set the Name to CPropertyListing and click Finish
- 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);
};
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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();
}
}
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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();
}
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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;
}
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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"======================================");
}
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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.");
}
|
- In the Class View, right-click CPropertyListing -> Add -> Function...
- 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 -=");
}
}
|
- 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();
}
|
- To create a new source file, on the main menu, click Project -> Add New
Item...
- In the Templates list, click C++ File (.cpp)
- Set the Name to Exercise and press Enter
- 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;
}
|
- Execute the application to test it