【问题标题】:Sorting a `List<object>` by object properties按对象属性对 `List<object>` 进行排序
【发布时间】:2012-08-28 10:42:05
【问题描述】:

我有一些不同的对象,它们都有一个名为Place 的整数字段。有没有办法在不知道实际对象是什么的情况下整理这个列表?我的意思是访问Place 字段并根据这个数字对列表进行排序。可能使用 linq 什么的?

一些示例对象:

public class Car
{
    public int Place;
    //Other related fields
}

public class Human
{
    public int Place;
    //Other related fields
}

//Somwhere in program
List<object> GameObjects;

【问题讨论】:

  • 您可以使用PropertyInfo 来完成。您是否有理由不使用一些常见的基础对象/接口?
  • Human 和 Car 都应该(直接或间接)从 WorldObject 或具有 Place 属性的东西派生。另一种选择是让它们都实现 IHavePlace 接口。该列表应该是 WorldObject 或 IHavePlace 类型。
  • 您可以为它们创建父类或接口

标签: c# linq sorting object ienumerable


【解决方案1】:

您应该从基类派生您的类。

public class Base
{
    public int Place;
}

public class Car : Base
{
    // other properties
}

public class Human : Base
{
    // other properties
}

然后您可以创建一个基本类型列表,添加人类 和汽车。之后你可以使用 Linq SortOrderBy 方法。

List<Base> list = new List<Base>();
list.Add(new Human { Place = 2 });
list.Add(new Car { Place = 1 });

var sortedList = list.Sort(x => x.Place);

更多信息

【讨论】:

  • 添加列表是 Base 类型的事实,你的答案是完美的。
【解决方案2】:

没有,因为object 没有Place 属性,只有Car/Human 有。

有几种方法可以解决这个问题:

引入基类

public class GameObject
{
    public int Place { get; set; }
}

public class Car : GameObject
{}

public class Human : GameObject
{}

...
List<GameObject> GameObjects

使用通用接口

public interface IGameObject
{
    int Place { get; }
}

public class Car : IGameObject
{
    public int Place { get; set; }
}

public class Human : IGameObject
{
    public int Place { get; set; }
}

List<IGameObject> GameObjects

【讨论】:

    【解决方案3】:

    您刚刚发现的是这些类型之间的关系。 CarHuman 似乎都有一个 Place 属性,所以你应该提取一个接口 à la IGameObject

    【讨论】:

      【解决方案4】:

      最好的方法是使用接口。如果不能,您仍然可以使用 dynamic 关键字进行后期绑定:

              var list = new List<object>
              {
                  new Car { Place = 3 },
                  new Human { Place = 1 },
                  new Car { Place = 2 }
              };
      
              var sortedList = list.OrderBy(o => ((dynamic)o).Place);
      

      【讨论】:

        【解决方案5】:

        是的,可以使用带反射的委托方法。据我所知,可能是其他一些巨头在不使用反射的情况下创建它

        【讨论】:

          【解决方案6】:

          你能做的最好的就是使用一个接口,像这样:

          public Interface IFoo
          {
            int place;
          }
          

          以及实现该接口:

          public class Car : IFoo
          {
              public int Place;
          }
          
          public class Human : IFoo
          {
              public int Place;
          }
          

          然后使用 linq:

          List<IFoo> GameObjects;
          
          GameObjects.OrderBy(g => g.Place);
          

          【讨论】:

            【解决方案7】:

            您可以让他们实现一个接口 IPlaceable 并使用属性而不是仅使用字段:

            public interface IPlaceable
            {
                int Place { get; set; }
            }
            
            public class Car : IPlaceable
            {
                public int Place { get; set; }
                //Other related fields
            }
            
            public class Human : IPlaceable
            {
                public int Place { get; set; }
                //Other related fields
            }
            
            
            // Somwhere in program
            List<IPlaceable> GameObjects;
            
            // Somwhere else
            GameObjects.OrderBy(go => go.Place);
            

            请注意,列表现在是 List&lt;IPlaceable&gt; 而不是 List&lt;Object&gt;

            【讨论】:

              猜你喜欢
              • 2022-08-19
              • 2023-03-27
              • 2021-05-11
              • 2020-08-03
              • 1970-01-01
              • 2016-02-08
              • 2013-02-12
              相关资源
              最近更新 更多