Predicates and OrderBy , Func
Question
I understand that predicates are delegate to function which return bool and take generic parameter, I understand that when I say:
mycustomer => mycustomer.fullname == 1
It actually means:
delegate (Customer mycustomer)
{
return mycustomer.fullName == "John";
}
The paramter I'm passing in when I pass this lambda expression is:
public delegate bool Criteria<T>(T value)
which is natively called Predicate
But what I don't understand is what it means when I say mycustomer=>mycustomer.fullname
In customers.OrderBy(mycustomer=>mycustomer.fullname);
How do I implement something like OrderBy
? How do I tell a method which property to do action on ! like the previous example?
By example here is a case I want to make a method which get all values of a collection for a specific property :
list<string> mylist = customers.GetPropertyValues(cus=>cus.Fullname);
Thanks in advance.
Solution
The Func<TElement,TKey>
is used to create an IComparer<TKey>
which is used internally in an OrderedEnumerable
to sort the items. When you do:
var items = myList.OrderBy(i => i.SomeProperty);
The OrderedEnumerable
type is creating an IComparer<TKey>
internally. In the above example, if i.SomeProperty
were a String
it would create an instance of IComparer<String>
and then sort the items in the source enumerable using that comprarer on the SomeProperty
member.
In your last case:
list<string> mylist = customers.GetPropertyValues(cus=>cus.Fullname);
You do this using Select
:
var names = customers.Select(c => c.Fullname);
Which will return an enumerable of String
names. In the Select
method, the Func<TSource, TResult>
is used to select the target element to be added to the result.
To replicate this yourself, you could do:
public static IEnumerable<TMember> GetPropertyValues<TSource, TMember>
(this IEnumerable<TSource> enumerable, Func<TSource, TMember> selector)
{
if (enumerable == null)
throw new ArgumentNullException("enumerable");
foreach (TSource item in enumerable)
{
yield return selector(item);
}
}
OTHER TIPS
You can create something like this:
static class ExtenstinonClass
{
static IEnumerable<V> GetPropertyValues<T, V>(this IList<T> collection, Func<T, V> func)
{
foreach(var item in collection)
{
yield retun func(item);
}
}
}
But I really don't understand why Select method doesn't suite you.
but what i dont understand is what it means when i say mycustomer=>mycustomer.fullname
It's the same thing as your delegate example except it only returns the fullName. Passed as a lambda so that it can be lazy evaluated.
If you want to create a method that works like OrderBy
, besides that your GetPropertyValues seems to be the same as customers.Select(c => c.Fullname)
, then you'll have to dive into the sea of generics and extension methods. OrderBy
is actually just an extension method on IEnumerable
defined as
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
It looks like the answer from @Mike is an example of that and also a reimplementation of LINQ Select
.