【问题标题】:Sorting list of Objects using LINQ and private IComparer?使用 LINQ 和私有 IComparer 对对象列表进行排序?
【发布时间】:2019-10-24 12:30:38
【问题描述】:

我的任务是拥有一个功能,使应用用户能够根据 RegisteredUser 对象的字段/属性值对其进行排序。

Assistant 类继承 RegisteredUser。我希望能够以某种方式利用lambdasLINQ 并对List<Assistants> 进行排序。有没有办法做到这一点?

public abstract class RegisteredUser  
{
    protected int id;
    protected bool active;
    protected string name;

    //other fields and methods

    public static IComparer sortUsersByName(Order order)
    {
            return (IComparer)new nameFieldComparator(order);
    }

    private class nameFieldComparator : IComparer
    {
        private Order direction;

        public nameFieldComparator(Order direction)
        {
            this.direction = direction;
        }

        public int Compare(object x, object y)
        {
            if (x != null && y != null)
            {
                RegisteredUser user1 = (RegisteredUser)x;
                RegisteredUser user2 = (RegisteredUser)y;

                return (int)this.direction * String.Compare(user1.Name, user2.Name);

            }
            else throw new ArgumentNullException("Objects cannot be compared!");
        }
    }
}

我的参考点是How to use IComparer。我在尝试不同的东西,没有成功。

Assistant a = new Assistant();
a.SetId(5);
a.Active = true;
a.Name = "asdasd"; 

Assistant f = new Assistant();
f.SetId(6);
f.Active = true;
f.Name = "asdf";


Assistant c = new Assistant();
c.Name = "a";
c.SetId(2);

List<RegisteredUser> l = new List<RegisteredUser>();
l.Add(a);
l.Add(f);
l.Add(c);
//list.Sort((x, y) => RegisteredUser.sortUsersByName()); of course, doesn't work...
List<Assistant> l = l.OrderBy() //tried bunch of ideas, but cannot get the syntax right

附:我是编程和 c# 新手

【问题讨论】:

  • @Izzy 您提供的链接中的可能解决方案与我想要实现的目标不兼容。你看我有私有 IComparable,现在不知道如何在一些 linq 表达式或 lambda 中调用它(通过公共方法)......
  • @MiljanPuletic 为什么要使用私有比较器,而不是简单的OrderBy(x=&gt;x.Name)?在任何情况下,OrderBy 都有一个接受 IComparer 的重载。在您的情况下,这只是名称的字符串比较器
  • 忽略这个问题,如果使用自定义IComparer,您可以自己设置顺序是正确的做法(我同意不是),如果您想这样做有一些问题这里。首先,这不会编译,因为RegisteredUser 没有Name 属性(它有一个name 字段,但它是受保护的,在IComparer 中不可用)。此外,您正在创建一个IComparer,但如果您想将其提供给OrderBy(Func&lt;TSource, TKey&gt;, IComparer&lt;TKey&gt;),您需要一个IComarer&lt;T&gt;,在这种情况下为IComparer&lt;RegisteredUser&gt;
  • @Izzy 你是对的。我将 NameComparator IComparer 放在单独的类中,当然是公开的,我会这样做:users.Sort(new NameComparator(Order.Ascending))。

标签: c# linq sorting icomparer


【解决方案1】:

使用 Linq 和 lambdas 试试这个:

 List<RegisteredUser> l = new List<RegisteredUser>();
 l.Add(a);
 l.Add(f);
 l.Add(c);

 var sortedList = l.OrderBy(x => x.Name).ToList();

【讨论】:

  • 但我希望以某种方式也能够通过 enum 命令,选择 asc od desc 命令
  • @MiljanPuletic 所有这些都可以通过 LINQ 使用 OrderBy 和OrderByDescending 获得。传递Order 没有什么意义,因为无论您想要什么排序顺序,comparison 结果都应该保持same1&lt;3 即使您想以相反的顺序对数字进行排序。 实际问题是什么?为什么要创建这样的私有比较器?
  • @PanagiotisKanavos 老实说,我不太清楚为什么。我想在文档中拥有相同/相似的 IComparer 实现。你能告诉我如何获取对象的升序和降序列表吗?
  • @MiljanPuletic g1b 有一点是没有必要实现 IComparer。他的例子很简单。您可以将它放在一个方法中并添加一个参数,说明它应该升序或降序排序(OrderBy vs OrderByDescending)。否则,请看这里:support.microsoft.com/nl-nl/help/320727/…。也许不用IComparer,而是IComparable
【解决方案2】:

这是IComparable的简单实现:

public abstract class RegisteredUser : IComparable
{
    public string Name { get; set; }

    // other properties


    public int CompareTo(object obj)
    {
        if (obj is RegisteredUser user)
            return this.Name.CompareTo(user.Name);

        return 1;
    }
}

public class Assistant : RegisteredUser
{

}

这是如何使用它:

var users = new List<RegisteredUser>();
users.Add(new Assistant() { Name = "John" });
users.Add(new Assistant() { Name = "Joe" });

users.Sort();

【讨论】:

    【解决方案3】:

    排序方法必须可以访问您的IComparer 实现,这意味着在这种情况下nameFieldComparator 必须是public class

    【讨论】:

      猜你喜欢
      • 2015-01-08
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多