A property is indexed if its get and set methods fit the following description.
- The get method has parameter tuple (T1, ..., TN), and has return type TR which can be any type.
- The set method has parameter tuple (T1, ..., TN , TR) and
void return type.
Given indexed property methods, a pseudo member array is injected with the following form (assuming property name F):
/* TR F[T1, ... ,TN ]; */ // compiler generated pseudo member
/* TR F[T1] ... [TN ]; */ // compiler generated pseudo member
A property provides array-like access to the pseudo member. However, because it is implemented using method calls, any parameter type can be used to index the pseudo member array.
Example
// __property2.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;
__gc class Employee {
public:
Employee(String * s, int d) {
_name = s;
_dept = d;
};
__property String * get_name() { return _name; }
__property int get_dept() { return _dept; }
private:
String * _name;
int _dept;
};
__gc class Manager {
public:
__property Employee * get_Report(String * s) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> name != s)
;
pEmp = pEmp -> next);
if (pEmp)
return pEmp -> emp;
else
return 0;
}
__property void set_Report(String* s, Employee* e) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> name != s)
;
pEmp = pEmp -> next);
if (!pEmp) {
EmpList * emp1 = new EmpList;
emp1 -> emp = e;
emp1 -> next = Reports;
Reports = emp1;
}
}
private:
__gc struct EmpList {
Employee * emp;
EmpList * next;
};
EmpList * pEmp;
static EmpList * Reports = 0;
};
/* Employee* Report[ String* ]; */ // pseudo array member
int main() {
Manager* Ed = new Manager;
Employee* Bob = new Employee(S"Bob Smith", 12);
Employee* Gus = new Employee(S"Gus Jones", 18);
// track Ed's reports
Ed->Report[ Bob->name ] = Bob; // indexed by String* type
Ed->Report[ Gus->name ] = Gus; // indexed by String* type
Console::WriteLine(Ed->Report[ Bob->name ]->dept);
} Output
The pseudo member array is indexed in a similar way to a C++ array.
Example
// __property3.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;
public __gc
class X {
public:
__property int get_Prop(int i, int j) {
return m_val - i - j;
}
__property void set_Prop(int i, int j, int value) {
m_val = value + i + j;
}
int m_val;
};
int main() {
X* x = new X;
x->Prop[1][2] = 3;
Console::WriteLine(x->Prop[1][2]);
} Output
An indexed property can be overloaded like any normal member function.
Example
// __property4.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;
__gc class PhoneNumber {
public:
PhoneNumber(int AreaCode, int ThreeDigits, int FourDigits) {
_AreaCode = AreaCode;
_ThreeDigits = ThreeDigits;
_FourDigits = FourDigits;
}
private:
int _AreaCode;
int _ThreeDigits;
int _FourDigits;
};
__gc class Employee {
public:
Employee(String * s, PhoneNumber * p) {
_name = s;
_phonenumber = p;
};
__property String * get_name() { return _name; }
__property PhoneNumber * get_number() { return _phonenumber; }
protected:
String * _name;
PhoneNumber * _phonenumber;
};
__gc class Manager {
public:
__property Employee * get_Report(String * s) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> name != s)
;
pEmp = pEmp -> next);
if (pEmp)
return pEmp -> emp;
else
return 0;
}
__property Employee * get_Report(PhoneNumber * p) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> number != p)
;
pEmp = pEmp -> next);
if (pEmp)
return pEmp -> emp;
else
return 0;
}
__property void set_Report(String* s, Employee* e) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> name != s)
;
pEmp = pEmp -> next);
if (!pEmp)
{
EmpList * emp1 = new EmpList;
emp1 -> emp = e;
emp1 -> next = Reports;
Reports = emp1;
}
}
/* Employee* Report[ String* ]; */ // pseudo array member
__property void set_Report(PhoneNumber * p, Employee* e) {
for (pEmp = Reports ; pEmp && (pEmp -> emp -> number != p)
;
pEmp = pEmp -> next);
if (!pEmp) {
EmpList * emp1 = new EmpList;
emp1 -> emp = e;
emp1 -> next = Reports;
Reports = emp1;
}
};
private:
__gc struct EmpList {
Employee * emp;
EmpList * next;
};
EmpList * pEmp;
static EmpList * Reports = 0;
};
int main() {
Manager* Ed = new Manager;
PhoneNumber * p1 = new PhoneNumber(425, 555, 1111);
PhoneNumber * p2 = new PhoneNumber(206, 555, 1111);
Employee* Bob = new Employee(S"Bob Smith", p1);
Employee* Gus = new Employee(S"Gus Jones", p2);
// track Ed's reports
Ed->Report[ Bob->name ] = Bob; // indexed by String*
Ed->Report[ Gus->number ] = Gus; // indexed by PhoneNumber*
Console::WriteLine(Ed->Report[ Bob->number ] -> name);
} Output