通过Lambda表达式对List <object>进行排序

时间:2015-06-01 13:12:11

标签: c# linq sorting

我有两种类型:

class Person 
{
  public string Name {get;set;}
  public string Car {get;set;}
}

和第二种类型:

class Employee
{
  public string Name {get;set;}
  public string Salary {get;set;}
}

其中属性 名称相同(两种类型)。
我也得到了列表:

List<Person> _ListPerson = new List<Person>
List<Employee> _ListEmployee = new List<Employee>();  

我添加了一些项目:

_ListPerson.Add( new Person { Name = "Jora" , Car = "BMW" };
_ListPerson.Add( new Person { Name = "Andrew" , Car = "Audi" };
_ListPerson.Add( new Person { Name = "Vasya" , Car = "Jiguli" };
_ListPerson.Add( new Person { Name = "Vasya" , Car = "Mercedes" };
_ListPerson.Add( new Person { Name = "Andy" , Car = "Renault" };  

_ListEmployee.Add(new Employee { Name = "Vasya", Salary = "1000$"};
_ListEmployee.Add(new Employee { Name = "Andy", Salary = "200$"};
_ListEmployee.Add(new Employee { Name = "Andrew", Salary = "5000$"};
_ListEmployee.Add(new Employee { Name = "Jora", Salary = "100$"};  

出于某种原因,我需要联合这些类型:

List<Object> People = New List<Object>();  
People.AddRange(_ListPerson);
People.AddRange(_ListEmployee);   

那么我如何通过lambda表达式排序这些家伙呢? 目前,我正在做这样的事情:

var _TEMP = _List.OfType<Person>().GroupBy(x => x.Name);....  //etc ,how i can use order by for these two types? Because oftype works only for one type.

2 个答案:

答案 0 :(得分:4)

最简单的方法是PersonEmployee共享一些公共基类或实现公共接口。例如:

public interface IName
{
    string Name { get; }
}

class Person : IName
{
    public string Name { get; set; }
    public string Car { get; set; }
}

class Employee : IName
{
    public string Name { get; set;}
    public string Salary { get; set;}
}

然后,您可以使用以下常见类型创建列表,而不是创建List<object>并使用OfType

var people = new List<IName>();  
people.AddRange(_ListPerson);
people.AddRange(_ListEmployee);

和小组:

var grouped = people.GroupBy(x => x.Name);

虽然您提到要排序,但实际上可以使用OrderByOrderByDescending进行排序:

var sorted = people.OrderBy(x => x.Name);

答案 1 :(得分:1)

正确这样做的方法是要么有一个共同的界面(根据查尔斯的答案)或一个共同的基类(正如彼得在查尔斯回答的评论中所建议的那样)。

由于员工很可能 Person,因此我认为让Employee派生自Person更有意义。所以:

public class Person
{
    public string Name { get; set; }
    public string Car { get; set; }
}

public class Employee : Person
{
    public string Salary { get; set;}
}

IName界面看起来有点不自然。当然,这不是模拟它的唯一方法。您还可以说Person 有一个作业:

public class Person
{
    public string Name { get; set; }
    public string Car { get; set; }
    public Job Job { get; set; }
}

public class Job
{
    public string Salary { get; set;}
    public Person Employee { get; set; }    
}

但是,如果您完全陷入困境且无法更改PersonEmployee类(可能来自某些第三方来源),那么可以执行像这样的东西:

var temp = People.Cast<dynamic>().OrderBy(a => a.Name);

将您的列表强制转换为dynamic,以便检查Name属性只会在运行时而不是编译时进行。但是,请注意,如果您在People列表中添加了一些没有Name属性的内容,那么您将收到运行时错误。

另一种选择是做这样的事情:

    var tenp = People.OrderBy(a => {
        string t = null;
        if (a is Person) {
            t = ((Person)a).Name;
        }
        else if (a is Employee) {
            t = ((Employee)a).Name;
        }
        return t;
    });

哪个更详细,但不需要dynamic。但是,在这种情况下,由于我没有添加else子句,因此任何非PersonEmployee的内容都将在null上排序,而 var abc; (function ($, W, D) { abc = {}; 可能不会是理想的行为。

希望这些解决方法的缺点将使大多数人相信,正确设计类层次结构以避免此问题会更好。即使你坚持使用你所给的类,根据具体用法,它可能值得将它们转换为更合理的层次结构,然后再使用它。