Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use C# delegate like functor in C++?

Tags:

c++

c#

In C++, to sort a vector, a list or any collection, I would use:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    vector<int> vt;
    vt.push_back( 3 );
    vt.push_back( 1 );
    vt.push_back( 2 );
    sort( vt.begin(), vt.end(), greater<int>() );
}

In C#, I found that List<> is equivalent to std::vector<>:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Professional_Csharp {
    class Program {
        static void Main( string[] args ) {
            List<int> intList = new List<int>();
            intList.Add( 3 );
            intList.Add( 2 );
            intList.Add( 1 );
            intList.Sort(); 
        }
    }
}

This worked fine, however if I want to customize the comparator, how could I implement that? Or if I want to sort just a specific range instead of the whole list? How could I do that?

Update

sort( vt.begin(), vt.begin() + 1 );

Is it possible in C#?

Thanks,
Chan

like image 756
Chan Avatar asked Dec 28 '22 01:12

Chan


2 Answers

Throughout the .NET framework you will occasionaly find methods (like Sort) which have one or more overloads which accept additional types (either interfaces or delegates) to extend their behavior. Unlike C++, .NET does not have the same approach as the STL to composable algorithms.

In the case of List.Sort there are two overloads that you may find useful:

List.Sort( IComparer<T> comparer )    // and
List.Sort( Comparison<T> comparison ) // .NET 4.0 and up

The first overload accepts an instance of a type that implements IComparer<T> - an interface with a single method Compare. The second overload is only available if you're using .NET 4.0 or newer - it accepts a delegate (or lambda expression) which supplies the comparison semantics.

If you can, the second overload is much easier to use:

intList.Sort( (a,b) => YourCompare(a,b) /* your compare logic here */ );

To use the first overload, you must create a class or struct that implements IComparer<T>:

public sealed class YourComparer : IComparer<YourType>
{
    int Compare( YourType a, YourType b ) { ... }
}

intList.Sort( new YourComparer() );

If you don't want to alter the collection itself, but only sort it's items and operate on them as a new sequence you can use LINQ's OrderBy operator:

intList.OrderBy( x => ... ).ToArray() /* creates new sequence, won't alter intList */


To answer the second part of your question, if you want to sort just a specific range of a particular collection, you would have to use the Sort( int, int, IComparer<T> ) overload.
like image 170
LBushkin Avatar answered Jan 10 '23 05:01

LBushkin


You can supply a comparison as a parameter to the sort method: http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx. I would supply an example, but the one in that MSDN article should suffice.

like image 37
Eric Mickelsen Avatar answered Jan 10 '23 05:01

Eric Mickelsen