tags:

views:

343

answers:

2

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

A: 

You might want to consider using Dynamic LINQ from the VS2008 Samples. Then you can do:

var orderedLines = poLines.OrderBy( poLineOrder ? "PartNumber" : "LineOrder" );
tvanfosson
Care to comment on the downvote?
tvanfosson
@tvanfosson, I got the same treatment for a different yet valid approach. Seems like someone just wanted to downvote :(
JaredPar
+3  A: 

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));
Dario