|
#include < vector >
#include < algorithm >
using std::vector;
using std::find;
using namespace System;
using namespace System::Collections::Generic;
ref class IntVector : ICollection< int >
{
public:
IntVector() : pVector(new vector< int >){}
~IntVector()
{
this->!IntVector();
}
!IntVector()
{
if (pVector != IntPtr::Zero)
{
delete static_cast< vector< int >* >(
pVector.ToPointer());
pVector = IntPtr::Zero;
}
}
property int Count
{
virtual int get();
}
property bool IsReadOnly
{
virtual bool get();
}
virtual void Add(int item);
virtual void Clear();
virtual bool Contains(int item);
virtual void CopyTo (array< int >^ array, int arrayIndex);
virtual bool Remove(int item);
virtual IEnumerator< int >^ GetEnumerator();
List< int >^ FindAll(Predicate< int >^ match)
{
if (match == nullptr)
throw gcnew NullReferenceException();
List< int >^ list = gcnew List< int >;
for each(int value in this)
{
if (match(value))
list->Add(value);
}
return list;
}
protected:
ref class IntVectorCollection : IEnumerator< int >
{
public:
IntVectorCollection(IntPtr vect) : pVector(vect),
index(0), IsReset(true) {}
~IntVectorCollection() {}
property int Current
{
virtual int get();
}
virtual bool MoveNext(void);
virtual void Reset(void);
private:
property Object^ UnTypedCurrent
{
virtual Object^ get(void)
sealed = System::Collections::IEnumerator::Current::get;
}
IntPtr pVector;
unsigned int index;
bool IsReset;
};
private:
virtual System::Collections::IEnumerator^ GetUntypedEnumerator(void)
sealed = System::Collections::IEnumerable::GetEnumerator;
IntPtr pVector;
};
Object^ IntVector::IntVectorCollection::UnTypedCurrent::get()
{
vector< int >* ptr = static_cast< vector< int >* >(pVector.ToPointer());
if (IsReset == true || index >= ptr->size())
{
throw gcnew System::ArgumentOutOfRangeException();
}
return (*ptr)[index];
}
bool IntVector::IntVectorCollection::MoveNext( void )
{
if (IsReset)
IsReset = false;
else
index++;
return (index < static_cast< vector< int >* >(
pVector.ToPointer())->size());
}
void IntVector::IntVectorCollection::Reset( void )
{
index = 0;
IsReset = true;
}
int IntVector::IntVectorCollection::Current::get()
{
vector< int >* ptr = static_cast< vector< int >* >(pVector.ToPointer());
if (IsReset == true || index >= ptr->size())
{
throw gcnew System::ArgumentOutOfRangeException();
}
return (*ptr)[index];
}
void IntVector::Add( int item )
{
static_cast< vector< int >* >(
pVector.ToPointer())->push_back(item);
}
void IntVector::Clear()
{
static_cast< vector< int >* >(
pVector.ToPointer())->clear();
}
bool IntVector::Contains( int item )
{
vector< int >::iterator result;
vector< int >* ptr = static_cast< vector< int >* >(pVector.ToPointer());
result = find(ptr->begin(), ptr->end(), item);
return result != ptr->end();
}
void IntVector::CopyTo( array< int >^ array, int arrayIndex )
{
vector< int >* ptr =
static_cast< vector< int >* >(pVector.ToPointer());
for (unsigned int i = 0; i < ptr->size(); ++i)
{
array[arrayIndex++] = (*ptr)[i];
}
}
bool IntVector::Remove( int item )
{
vector< int >::iterator result;
vector< int >* ptr = static_cast< vector< int >* >(pVector.ToPointer());
result = find(ptr->begin(), ptr->end(), item);
if (result == ptr->end()) return false;
ptr->erase(result);
return true;
}
IEnumerator< int >^ IntVector::GetEnumerator()
{
return gcnew IntVectorCollection(pVector);
}
System::Collections::IEnumerator^ IntVector::GetUntypedEnumerator( void )
{
return gcnew IntVectorCollection(pVector);
}
int IntVector::Count::get()
{
return static_cast< vector< int >* >(
pVector.ToPointer())->size();
}
bool IntVector::IsReadOnly::get()
{
return false;
}
ref class CompareInt
{
public:
CompareInt(int value) : filter(value) {}
bool IsLessThan(int value)
{
return value < filter;
}
private:
int filter;
};
int main(array< System::String ^ > ^args)
{
IntVector^ vctr = gcnew IntVector;
vctr->Add(10);
vctr->Add(20);
vctr->Add(30);
vctr->Add(40);
vctr->Add(50);
vctr->Add(60);
vctr->Add(70);
vctr->Add(80);
vctr->Add(90);
vctr->Add(100);
for each (int value in vctr)
{
Console::WriteLine(value);
}
Console::WriteLine();
if (vctr->Remove(30))
{
for each (int value in vctr)
{
Console::WriteLine(value);
}
}
Console::WriteLine();
List< int >^ values =
vctr->FindAll(gcnew Predicate< int >(
gcnew CompareInt(60), &CompareInt::IsLessThan));
for each (int value in values)
{
Console::WriteLine(value);
}
return 0;
}
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
IEnumerator< T > inherits from the non-generic IEnumerator and IDisposable . In order to satisfy IDisposable 's requirments, you must create a destructor in your derived class. Also, since C++/CLI does not overload methods by signature, I used Named Virtual Overriding on Object^ Current get property to satisfy the compiler.
ref class CKLEnumerator : public IEnumerator< CK >
{
public:
CKLEnumerator(ConcatenatedKeyLinkedList^ cl)
: list(cl) {}
~CKLEnumerator(void) {}
property CK Current
{
virtual CK get(void)
{
...
}
}
virtual bool MoveNext(void)
{
...
}
virtual void Reset(void)
{
...
}
private:
property Object^ UnTypedCurrent
{
virtual Object^ get(void)
sealed = System::Collections::IEnumerator::Current::get
{
throw gcnew System::NotSupportedException();
}
}
protected:
ConcatenatedKeyLinkedList^ list;
};
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
The array<T> and List<T> classes use the Predicate<T> delegate that represents a function or method used for filtering data. In C++/CLI, I have found a little trick where you can pass in your limiting values into any of the above classes' methods that require this delegate in one line:
using namespace System;
ref class Compare
{
public:
Compare(int lowerLimit, int upperLimit)
: lower(lowerLimit), upper(upperLimit) {}
bool Between(int value)
{
return value >= lower && value <= upper;
}
private:
int lower;
int upper;
};
int main(array<System::String ^> ^args)
{
array<int>^ values = { 8, 12, 18, 23, 24, 31, 42, 52, 65, 99, 101 };
array<int>^ results = array<int>::FindAll(values,
gcnew <span style="color: navy; font-weight: bolder">Predicate<int>(gcnew Compare(21, 65), &Compare::Between)</span>);
for each (int result in results)
Console::WriteLine(result);
return 0;
} This isn't any jaw-dropping code; however, you can not do that in C#!
-- modified at 21:52 Tuesday 24th July, 2007
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|