Search code examples
c#delegatesnullable

Delegate creator to create comparitor for nullable types


I'm using a custom ListView control that cannot handle null values with its internal comparing methods. My dream would be for comparison to just work, without much configuration.

Most of the columns have values of nullable decimal type, but some have other types, like nullable integers or non-nullable types.

Currently for every colum I have to write:

_priceColumn.Comparitor = delegate (object x, object y)
{
    Ticker xTicker = (Ticker)x;
    Ticker yTicker = (Ticker)y;

    return Nullable.Compare<Decimal>(xTicker.Price, yTicker.Price);
};

I would like to be able to write something like:

_priceColumn.Comparitor = ColumnHelpers.CreateNullableComparitor(Ticker.Price) //It would have to look up the type of Ticker.Price itself and call the correct Nullable.Compare.

or

_priceColumn.Comparitor = ColumnHelpers.CreateNullableComparitor(Ticker.Price, Decimal?) //I pass  Decimal? to it, which is the type of Ticker.Price

I don't know how to make it create something that matches the signature of the required delegate.

Its probably easy to solve with some generic magic or by checking the type and choosing the correct method.

The custom ListView that I'm using is this one: https://www.codeproject.com/Articles/20052/Outlook-Style-Grouped-List-Control


Solution

  • Assuming you want your method to return a Comparison<object>. You can write such a method:

    public static Comparison<object> CreateNullableComparitor<T>(Func<Ticker, T?> keySelector) where T: struct {
        return (o1, o2) => Comparer<T>.Default.Compare(keySelector((Ticker)o1), keySelector((Ticker)o2));
    }
    

    And use it like so:

    CreateNullableComparitor(x => x.Price);
    

    If the value's type is non-nullable, type inference does not work here, so you'll have to do:

    CreateNullableComparitor<decimal>(x => x.NonNullablePrice);