【问题标题】:OrderBy keySelector with different data types on TKeyOrderBy keySelector 在 TKey 上有不同的数据类型
【发布时间】:2019-10-22 08:43:28
【问题描述】:

我需要一个返回 keySelector 的方法,它可以在调用 OrderBy 表达式时使用。问题是 keySelector 是一个通用委托,我希望该方法在 TKey 上返回具有不同数据类型的 keySelector:

Func<TSource,TKey> keySelector

我想完成此操作,但不是使用 lambda 表达式,而是使用返回 keySelector(TKey=string 或 int)的方法:

IEnumerable<Person> orderedByFirstName = persons.OrderBy(p => p.FirstName);
IEnumerable<Person> orderedByAge = persons.OrderBy(p => p.Age);

是否有可能以某种方式在 TKey 上返回具有不同类型的 keySelector 的方法?不可能返回 lambda 表达式,但是类似的东西......

只要该方法只返回数据类型字符串的 keySelectors 一切正常:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class Behavior
{
    public virtual string GetOrderByKeySelector(Person p)
    {
        return p.FirstName;
    }
}

public class SpecializedBehavior : Behavior
{
    public override string GetOrderByKeySelector(Person p)
    {
        return p.LastName;
    }
}

List<Person> persons = new List<Person>
{
    new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
    new Person{Age=90, FirstName="Nils", LastName="Nilsson"}, 
    new Person{Age=15, FirstName="Olle", LastName="Johansson"},
    new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
};

这样使用:

SpecializedBehavior behavior = new SpecializedBehavior();
IEnumerable<Person> orderedResult = persons.OrderBy(behavior.GetOrderByKeySelector);

【问题讨论】:

  • 这是可能的,但你从GetorderByKeySelector返回string而不是Func&lt;TSource,TKey&gt;,所以这显然不起作用
  • 如何实现IComparer&lt;Person&gt;,然后执行persons.OrderBy(p =&gt; p, behavior)?然后你可以在里面比较你想要的任何东西。

标签: c# linq generics expression-trees


【解决方案1】:

如何将集合改为方法。

void Main()
{
    SpecializedBehavior behavior = new SpecializedBehavior();
    IEnumerable<Person> orderedResult = behavior.Sort(persons);
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class Behavior
{
    public virtual IEnumerable<Person> Sort(IEnumerable<Person> persons)
    {
        return persons.OrderBy(p => p.FirstName);
    }
}

public class SpecializedBehavior : Behavior
{
    public override IEnumerable<Person> Sort(IEnumerable<Person> persons)
    {
        return persons.OrderBy(p => p.Age);
    }
}


List<Person> persons = new List<Person>
{
    new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
    new Person{Age=90, FirstName="Nils", LastName="Nilsson"},
    new Person{Age=15, FirstName="Olle", LastName="Johansson"},
    new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
};

【讨论】:

  • 如果我找不到问题的解决方案,我已经将您的解决方案视为我的后备方案!我使用 List 的方法而不是 OrderBy:public void Sort (Comparison comparison)
【解决方案2】:

这个答案只是为了说明@LasseVågsætherKarlsen 的评论,所有的功劳都应该归功于他:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

public class PersonByFirstNameComparer : IComparer<Person>
{
    public int Compare(Person left, Person right) =>
        left.FirstName.CompareTo(right.FirstName);
}

public class Behavior
{
    public virtual IComparer<Person> GetComparer() => PersonByFirstNameComparer();
}

public class PersonByLastNameComparer : IComparer<Person>
{
    public int Compare(Person left, Person right) =>
        left.LastName.CompareTo(right.LastName);
}

public class SpecializedBehavior : Behavior
{
    public override IComparer<Person> GetComparer() => new PersonByLastNameComparer();
}

可以通过以下方式使用:

public static void Main()
{
    var people = new List<Person>
    {
        new Person{Age=10, FirstName="Pelle", LastName="Larsson"},
        new Person{Age=90, FirstName="Nils", LastName="Nilsson"}, 
        new Person{Age=15, FirstName="Olle", LastName="Johansson"},
        new Person{Age=30, FirstName="Kalle", LastName="Svensson"}
    };

    var standardBehavior = new Behavior();
    IEnumerable<Person> orderedPeople1 = 
        people.OrderBy(p => p, standardBehavior.GetComparer());

    foreach (Person p in orderedPeople1)
    {
        Console.WriteLine($"{p.FirstName} {p.LastName}");
    }

    var specializedBehavior = new SpecializedBehavior();
    IEnumerable<Person> orderedPeople2 = 
        people.OrderBy(p => p, specializedBehavior.GetComparer());

    foreach (Person p in orderedPeople2)
    {
        Console.WriteLine($"{p.FirstName} {p.LastName}");
    }
}

Link to fiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多