关于排序:c#自定义属性上的排序列表

C# : Sort list on custom property

本问题已经有最佳答案,请猛点这里访问。

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

我有一个班级叫MyDate,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

1
2
3
4
5
public class MyEvent
{
  public int EventId{get;set;}
  public MyDate StartDate{get;set;}
}

我收集了我喜欢的

1
List<MyEvent> myEvents.

现在我需要按StartDate的降序对MyEvents进行排序。我的问题是无法添加IComparable或更改MyDate,因为它是由其他团队编写的,我只是引用了DLL。我无法控制我的日期代码。有人能帮我怎么做吗?我创建了一个新的比较器类,该类实现了IComparer,但无法理解如何使用它并对MyEvents进行排序。

**更新1 **

非常感谢阿列克谢、埃桑和戴夫帮助我。我试过戴夫的回答,但效果很好。我试图用更好的方法来做,这样就不需要添加任何新属性。我没有尝试使用StringDateCorler的ehsan方法,但它帮助我理解如何在LINQ语句中使用Comparer。最后,正如阿列克谢所指出的,我做了如下的事

**更新2 **

有时,我会得到e2.startdate.mmddyyhhmmss和/或e2.startdate.mmddyyhhmmss的空字符串,因此我更改了下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
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
                    }
            );


您可以根据需要用linq OrderyBy()OrderByDescending方法编写:

1
2
3
4
5
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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对象为参数:

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


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

1
2
3
4
5
6
7
8
public class MyEvent
{
    public int EventId{get;set;}
    public MyDate StartDate{get;set;}
    public DateTime MyStartDate { get { return DateTime.Parse(StartDate.MMDDYYYYHHMMSS); } }
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyEvent
{
    public MyEvent(int eventId, MyDate startDate)
    {
        EventId = eventId;
        StartDate = startDate;
        MyStartDate = DateTime.Parse(StartDate.MMDDYYYYHHMMSS);
    }

    public int EventId{get; private set;}
    public MyDate StartDate{get; private set;}
    public DateTime MyStartDate { get; private set; }
}