|
|
| How to code an IComparer to use for ArrayList.Sort(IComparer)? |
|
| Author |
Message |
Dave111

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
The MSDN documentation gives a sample of code for how to implement this here: http://msdn2.microsoft.com/en-us/library/0e743hdt.aspx
What their implentation does is sorts an ArrayList of strings in descending order (or reversed). In my program, I have an ArrayList of 'Record' objects that contains several properties for data fields. What I obviously want to be able to do is sort the ArrayList on each one of these data properties. I am not sure what the syntax is doing here and wanted to know if anyone knew what I would have to do to make an IComparer interface to handle object properties.
Thanks in advance
Visual C++8
|
| |
|
| |
 |
Gordon Hogenson - MSFT

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
If I understand your scenario correctly, you could probably add a enum property to your class that implements IComparer that represents the data properties you can sort on.
using namespace System;
using namespace System::Collections;
void PrintIndexAndValues( IEnumerable^ myList );
enum class SortFieldEnum { Field1 = 1, Field2 = 2 };
ref class MyObjectType
{
public :
int Field1;
String^ Field2;
};
ref class myComparerClass: public IComparer
{
public :
property SortFieldEnum SortField;
// Calls CaseInsensitiveComparer.Compare with the parameters reversed.
virtual int Compare( Object^ x, Object^ y ) = IComparer::Compare
{
MyObjectType^ obj1 = (MyObjectType^) x;
MyObjectType^ obj2 = (MyObjectType^) y;
CaseInsensitiveComparer^ comparer = gcnew CaseInsensitiveComparer();
switch (SortField)
{
case SortFieldEnum::Field1:
if ( obj1->Field1 > obj2->Field1)
return 1;
else if (obj1->Field1 < obj2->Field1)
return -1;
else return 0;
break;
case SortFieldEnum::Field2:
return (comparer->Compare( obj1->Field2, obj2->Field2 ));
break;
default:
; /* if this is an error case, throw an exception */
}
}
};
Does this help Was your question about the syntax
return ((gcnew CaseInsensitiveComparer())->Compare(y, x);
This just creates a new object and then invokes the method on it, returning the result. It's equivalent to:
CaseInsensitiveComparer comparer = gcnew CaseInsensitiveComparer();
return comparer->Compare(y, x);
|
| |
|
| |
 |
Dave111

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
If I was to implement this in the main, would this be correct syntax
int main(array<System::String ^> ^args) { ArrayList ^myList = gcnew ArrayList(10); // assuming a constructor for this MyObjectType ^obj1 = gcnew MyObjectType(3, "Sally"); MyObjectType ^obj2 = gcnew MyObjectType(2, "Mary"); MyObjectType ^obj3 = gcnew MyObjectType(1, "John"); myList->Add(obj1); myList->Add(obj2); myList->Add(obj3); IComparer^ myComparer = gcnew myComparerClass(); myComparer->SortFieldEnum::Field1; // to sort on the integer field myList->Sort( myComparer ); myComparer->SortFieldEnum::Field2; // to sort on the String field myList->Sort( myComparer ); return 0; }
|
| |
|
| |
 |
Dave111

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
Gordon, I tried using your enum method. My program uses a multifile assembly dll, so I wanted to just add a header(.h) and an implementation file(.cpp) and compile it into my existing assembly. When building the assembly I get the following compliation errors: Compiling... RecordComparer.cpp .\RecordComparer.cpp(10) : error C2761: 'int Bankers::RecordComparer::Compare(System::Object ^,System::Object ^)' : member function redeclaration not allowed .\RecordComparer.cpp(10) : fatal error C1903: unable to recover from previous error(s); stopping compilation
RecordComparer.h
using namespace System; using namespace System::Collections; namespace Bankers { enum class SortFieldEnum { ssn = 1, name = 2, bal = 3 }; public ref class RecordComparer : public IComparer { public: property SortFieldEnum SortField; virtual int Compare( Object^ x, Object^ y ) = IComparer::Compare; }; }
RecordComparer.cpp:
#include "stdafx.h" using namespace System; #include "Personal_Record.h" #include "RecordComparer.h" using namespace Bankers;
virtual int RecordComparer::Compare( Object^ x, Object^ y ) = IComparer::Compare { Personal_Record ^obj1 = (Personal_Record^) x; Personal_Record ^obj2 = (Personal_Record^) y; CaseInsensitiveComparer^ comparer = gcnew CaseInsensitiveComparer();
switch (SortField) { case SortFieldEnum::ssn: if ( obj1->p_ssn > obj2->p_ssn) // p_ssn type: property UInt64 return 1; else if (obj1->p_ssn < obj2->p_ssn) return -1; else return 0; break; case SortFieldEnum::bal: if ( obj1->p_balance > obj2->p_balance) // p_ssn type: property Double return 1; else if (obj1->p_balance < obj2->p_balance) return -1; else return 0; break; case SortFieldEnum::name: return (comparer->Compare( obj1->p_lName, obj2->p_lName )); // p_lName type: property String^ break; }
I know this kind of deviates from my original question, but if I still need to be able to implement this to test the Sort() method. Thanks
|
| |
|
| |
 |
Gordon Hogenson - MSFT

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
The "virtual" and the " = IComparer::Compare" are part of the declaration, so it's appropriate to include that in the class declaration, but not in the definition. Remove those from the definition in the .cpp file and you should be good.
|
| |
|
| |
 |
Gordon Hogenson - MSFT

|
Posted: Visual C++ Language, How to code an IComparer to use for ArrayList.Sort(IComparer)? |
Top |
Yes, the main method you have looks reasonable. You might consider a few improvements over my model, such as having the constructor set a reasonable default value.
|
| |
|
| |
 |
| |
|