C#:自定义属性上的排序列表[重复]

Posted

技术标签:

【中文标题】C#:自定义属性上的排序列表[重复]【英文标题】:C# : Sort list on custom property [duplicate] 【发布时间】:2015-09-15 18:05:53 【问题描述】:

如果这是重复的,我很抱歉。请指出正确的问题。

我有一个名为 MyDate 的类,如下所示

public class MyDate

    private SqlDateTime m_dateTime;

    public MyDate(DateTime dateTime)
    
       if (DateTime.Compare(dateTime, (DateTime)SqlDateTime.MinValue) <= 0)
            m_dateTime = SqlDateTime.MinValue;
        else
            m_dateTime = dateTime;
    

    public string MMDDYYYYHHMMSS
    
       get
         
            if(m_dateTime > SqlDateTime.MinValue)
                return m_dateTime.Value.ToString("MM/dd/yyyy hh:mm:ss tt");
            else
                return String.Empty;
         
    

我有一个名为 MyEvent 的类,如下所示

public class MyEvent

  public int EventIdget;set;
  public MyDate StartDateget;set;

我收集了类似的 MyEvent

List<MyEvent> myEvents. 

现在我需要按 StartDate 的降序对 myEvents 进行排序。我遇到的问题是我无法添加 IComparable 或更改 MyDate,因为它是由其他团队编写的,我只是引用 dll。我无法控制 MyDate 代码。任何人都可以帮助我怎么做。我创建了一个新的比较器类,它实现了 IComparer,但无法理解如何使用它并对 myEvents 进行排序。

**更新 1 **

非常感谢 Alexei、Ehsan 和 Dave 帮助我。我试过戴夫的回答,它奏效了。我试图以更好的方式做到这一点,这样就不需要添加任何新属性。我没有尝试 Ehsan 使用 StringDateComparer 的方式,但它帮助我了解了如何在 Order linq 语句中使用 Comparer。最后正如阿列克谢所指出的那样,我确实喜欢下面

**更新 2 **

有时我得到 e2.StartDate.MMDDYYYYHHMMSS 和/或 e2.StartDate.MMDDYYYYHHMMSS 的空字符串,所以我更改了如下代码

myEvents.Sort(
                delegate(MyEvent e1, MyEvent e2)
                 
                     DateTime dt1;
                     DateTime dt2;
                     DateTime.TryParse(e1.StartDateTime.MMDDYYYYHHMMSS, out dt1);
                     DateTime.TryParse(e2.StartDateTime.MMDDYYYYHHMMSS, out dt2);

                     return dt2.CompareTo(dt1); // descending
                     //return dt1.CompareTo(dt2); // ascending
                    
            );

【问题讨论】:

不完全重复,OP场景不同 接受DateTime 的类转换为SqlDateTime 并且只公开string?你真正的问题是另一个团队。 您显然已经看到了我认为是 duplicate 的问题,因为它首先链接到搜索您的帖子标题 (bing.com/search?q=C%23+%3A+Sort+list+on+custom+property)。请澄清为什么建议的解决方案不起作用(包括自定义比较器),因此很明显这篇文章不是重复的。 我的情况不同。在 MyDate 我没有任何 DateTime 属性。所以我不能按方法使用任何排序或顺序。我试图避免在 MyEvent 类中添加额外的属性。我试过 IComparer。我看到的所有示例都只是直接使用 OrderBy linq 语句跳转,而没有显示 IComparer 实现是如何形成的...... @Ziggler ***.com/a/3309397/477420 展示了自定义比较器的完美示例... 【参考方案1】:

这可能效率不高,但您可以将 DateTime 属性添加到您的 MyEvent 类,将 StartDate 转换为 DateTime 并对其进行排序:

public class MyEvent

    public int EventIdget;set;
    public MyDate StartDateget;set;
    public DateTime MyStartDate  get  return DateTime.Parse(StartDate.MMDDYYYYHHMMSS);  


var sorted = myEvents.OrderByDescending(e => e.MyStartDate);

或者,您可以使类不可变并在实例化它时进行转换:

public class MyEvent

    public MyEvent(int eventId, MyDate startDate)
    
        EventId = eventId;
        StartDate = startDate;
        MyStartDate = DateTime.Parse(StartDate.MMDDYYYYHHMMSS);
    

    public int EventIdget; private set;
    public MyDate StartDateget; private set;
    public DateTime MyStartDate  get; private set; 

【讨论】:

更好的是在创建MyEvent 并使MyEvent 不可变时设置MyStartDate 属性.. 非常感谢。我试过了,它奏效了。我试图以更好的方式做到这一点,这样就不需要添加任何新属性【参考方案2】:

您可以根据需要使用Linq OrderyBy()OrderByDescending 方法这样编写:

var outputDate = myEvents.OrderByDescending(x=>
                          
                           DateTime parsedDate;
                           return DateTime.TryParseExact(x.StartDate, "MM/dd/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate) ? parsedDate : DateTime.MinValue;
                          );

或者正确的方法是为它创建一个自定义IComparer:

public class StringDateComparer : IComparer<string>


    public int Compare(string date1, string date2)
    
        DateTime parsedDate1;
        DateTime.TryParseExact(date1, "MM/dd/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate1);


        DateTime parsedDate2;
        DateTime.TryParseExact(date2, "MM/dd/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate2);



        if (parsedDate1 < parsedDate2)
            return -1;
        if (parsedDate1 > parsedDate2)
            return 1;


        return 0;
    

现在调用OrderByDescending() 重载,它将IComparer 对象作为参数:

var outputDate = myEvents.OrderByDescending(x=>x.StartDate,new StringDateComparer());

【讨论】:

非常感谢。我没有尝试过,但它帮助我了解了如何在 Order linq 语句中使用比较器

以上是关于C#:自定义属性上的排序列表[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java 8:按属性对对象列表进行排序,无需自定义比较器

c# 如何根据自定义变量来生成 属性get set

c# 用户自定义控件的问题 winform

根据自定义对象属性从数组列表中删除元素

c# winform 制作自定义控件

使用 c# 对自定义链接列表进行排序