I would like to be able to pass in a Func<T, ?> that allows me to choose exactly how to sort a list of items... the issue I have is the the return type might vary... so for example I want to do something like this (not production code):
Func<POline, string> poLineOrder
if (option) poLineOrder = poline => poline.PartNumber;
else poLineOrder = poline => poline.LineOrder;
var orderedLines = poLines.OrderBy(poLineOrder);
The issue here is that while PartNumber is a string, LineOrder is an int, and this code doesn't compile. I have a feeling I'm going to have to build an Expression (?) but I can't seem to get the syntax right.
(Yes, I can solve this, by using poline.LineOrder.ToString("D10") but I'm asking the more general question here... thanks!)
-mdb
In LINQ, the OrderBy operator is used to sort the list/ collection values in ascending order. In LINQ, if we use order by the operator by default, it will sort the list of values in ascending order. We don't need to add any ascending condition in the query statement.
This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved.
The term 'Lambda expression' has derived its name from 'lambda' calculus which in turn is a mathematical notation applied for defining functions. Lambda expressions as a LINQ equation's executable part translate logic in a way at run time so it can pass on to the data source conveniently.
OrderBy
expects a Key-Selector-function of type Func<Item, Key>
and an optional IComparer<Key>
to define the comparison itself.
You'll need the following helper definitions:
class FunctorComparer<T> : IComparer<T> {
private readonly Comparison<T> m_Comparison;
public FunctorComparer(Comparison<T> Comparison) {
this.m_Comparison = Comparison;
}
public int Compare(T x, T y) {
return m_Comparison(x, y);
}
}
static Comparison<TKey> Compare<TKey, TRes>(Func<TKey, TRes> Selector) where TRes : IComparable<TRes> {
return (x, y) => Selector(x).CompareTo(Selector(y));
}
Now you can write
Comparison<POLine> x;
if (option)
x = Compare<POLine, int>(l => l.PartNumber);
else
x = Compare<POLine, string>(l => l.LineOrder);
var res = poLines.OrderBy(i => i, new FunctorComparer<POLine>(x));
You might want to consider using Dynamic LINQ from the VS2008 Samples. Then you can do:
var orderedLines = poLines.OrderBy( poLineOrder ? "PartNumber" : "LineOrder" );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With