Есть ли способ вернуть разные KeySelectors в один OrderBy? - PullRequest
2 голосов
/ 21 февраля 2012

У меня длинная линия с OrderBy внутри.Эта строка повторяется несколько раз с небольшим отличием:

OrderBy(m => m.Name)
OrderBy(m => m.CreationTime)

и т. Д.

В целях удобства обслуживания существует ли способ сделать только одну строку и вызвать ее несколькометод, или, возможно, использовать некоторые Action, которые позаботятся о возвращении правильного поля?Проблема в том, что поля не одного типа.

Ответы [ 4 ]

4 голосов
/ 21 февраля 2012

Посмотрите на сигнатуру этого метода:

public static IOrderedEnumerable OrderBy (этот источник IEnumerable, Func keySelector, компаратор IComparer)

Вам нужно дать его IComparer<TKey>

data.OrderBy(x => x, new FooComparer());
data.OrderBy(x => x, new BarComparer());
data.OrderBy(x => x, new BazComparer());

Не уверен, что гораздо проще создавать классы только для сортировки ...

Вы также можете создавать различные методы, которые сортируют список в соответствии с перечислением, которое они получают в качестве параметра,
Я думаю, что это намного более чистое решение.

MSDN

1 голос
/ 21 февраля 2012

Может быть, это ближе к тому, что вы хотите

public IComparable GetKey(int keyNum)
{
    switch (keyNum) {
        case 1:
            return Name;
        case 2:
            return CreationTime;
        default:
            return null;
    }
}

Сортировка будет происходить так

.OrderBy(m => m.GetKey(1))

Еще один способ - вернуть делегата

public static Func<MyClass, IComparable> GetKeySelector(int keyNum)
{
    switch (keyNum) {
        case 1:
            return m => m.Name;
        case 2:
            return m => m.CreationTime;
        default:
            throw new ArgumentException();
    }
}

.OrderBy(MyClass.GetKeySelector(1));
0 голосов
/ 21 февраля 2012

После OrderBy вы должны использовать ThenBy

.OrderBy(m => m.Name)
.ThenBy(m => m.CreationTime)

Но это не отвечает на ваш вопрос.Реализуйте IComparable<Type_of_m> в типе m, тогда вы можете сравнить с

.OrderBy(m => m)

class Type_of_m : IComparable<Type_of_m>
{
    public string Name { get; set; }
    public DateTime CreationTime { get; set; }

    public int CompareTo(Type_of_m other)
    {
        int comp = Name.CompareTo(other.Name);
        if (comp != 0) {
            return comp;
        }
        return CreationTime.CompareTo(other.CreationTime);
    }
}

Если вы хотите заказать элементы несколькими способами, тогдаиспользуйте Comparer, как объяснил Гдорон.Это хороший случай для вложенных классов.

class MyClass
{
    public string Name { get; set; }
    public DateTime CreationTime { get; set; }

    public static readonly IComparer<MyClass> NameComparer = new MyNameComparaer();
    private class MyNameComparaer : IComparer<MyClass>
    {
        public int Compare(MyClass x, MyClass y)
        {
            return x.Name.CompareTo(y.Name);
        }
    }

    public static readonly IComparer<MyClass> DateComparer = new MyDateComparer();
    private class MyDateComparer : IComparer<MyClass>
    {
        public int Compare(MyClass x, MyClass y)
        {
            return x.CreationTime.CompareTo(y.CreationTime);
        }
    }
}

Затем вы можете заказать так:

.OrderBy(m => m, MyClass.NameComparer)

или вот так

.OrderBy(m => m, MyClass.DateComparer)
0 голосов
/ 21 февраля 2012

Звучит так, как будто вы копируете один и тот же весь выбор несколько раз? Вам просто нужно это:

.OrderBy(m=>m.Name)
.ThenBy(m=>m.CreationTime);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...