pelt
pelt

Reputation: 113

How to pass search parameter, into function that will search a c# collection

Assume I have a collection of the form:

List<Member> myMembers= new List<Member>() 
{ 
    new Member(){ID=1,FirstName="John",LastName="Doe"}, 
    new Member(){ID=3,FirstName="Allan",LastName="Jones"}, 
    new Member(){ID=2,FirstName="Martin",LastName="Moe"}, 
    new Member(){ID=4,FirstName="Ludwig",LastName="Issac"} 
};

I can sort this list via FirstName by using:

myMembers.Sort((x, y) => x.FirstName.CompareTo(y.FirstName)); 

I would like to do this inside of a function, so that I can pass the desired search parameter. Something like:

public void sortCollection( parameter SearchTerm, List<Member> myCollection )
{
    myCollection ((x, y) => x.SearchTerm.CompareTo(y.FirstName)); 
}

Obviously here, I cannot pass in the desired search field this way, but is it possible to do what I am asking?

Upvotes: 0

Views: 173

Answers (4)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23228

You can create a generic extension method for that and pass Func<T, TResult> delegate to it, which is used as key selector for built-in Sort method

public static void SortExt<T, TValue>(this List<T> collection, Func<T, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    collection.Sort((x, y) => comparer.Compare(selector(x), selector(y)));
}

Keep in mind that you should compare the same fields of compared objects.

Example of the usage

myMembers.SortExt(member => member.FirstName);

If you want to compare the myMembers collection only, the declaration can be simplified

public static void SortExt<TValue>(this List<Member> members, Func<Member, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    members.Sort((x, y) => comparer.Compare(selector(x), selector(y)));
}

Another option is to introduce a Comparison<T> delegate instance to store the logic of field comparison and pass it to the Sort method. Here you can specify any custom comparison that you want

Comparison<Member> comparison = (x, y) => x.FirstName.CompareTo(y.FirstName);
myMembers.Sort(comparison);

Upvotes: 1

Stefan
Stefan

Reputation: 672

Why not simply use the built in function?

myMembers.OrderBy(m => m.FirstName)

If you really want to, you can write your own wrapper around this function, but the call would look more or less identical and would kind of be reinventing the wheel.

something like this extension method:

public static IEnumerable<T> OrderByWrapper<T, TKey>(this IEnumerable<T> source, Func<T,TKey> keySelector)
{
    return source.OrderBy(keySelector);
}

you would call it with:

myMembers.OrderByWrapper(m => m.FirstName)

Upvotes: 0

Prasad Telkikar
Prasad Telkikar

Reputation: 16059

Instead of writing one more wrapper on Linq .OrderBy() or .Sort() method and calling that where ever you want to sort, use Linq OrderBy() or .Sort() method

Use Sort() like

//If you want to sort collection by Id then
myMembers.Sort(x => x.Id); 

//If you want to sort collection by FirstName then
myMembers.Sort(x => x.FirstName);

...

To decide between OrderBy()/Sort() read below Q&A thread

C# Sort and OrderBy comparison

Upvotes: 0

Nguyễn Văn Phong
Nguyễn Văn Phong

Reputation: 14218

Demo on dotnet fiddle

It seems to me that you can use Func<> to be able to dynamic order by.

var result = sortCollection(p => p.ID, myMembers);

public static IEnumerable<Member> sortCollection(Func<Member, object> keySelector, List<Member> myCollection)
{
    return myCollection.OrderBy(keySelector);
}

Read the following post to have a better understanding

Dynamic Order By in Linq

Upvotes: 0

Related Questions