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





PostPosted: 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://www.hide-link.com/

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++1  
 
 
Gordon Hogenson - MSFT





PostPosted: 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





PostPosted: 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





PostPosted: 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





PostPosted: 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





PostPosted: 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.