2015-09-15 4 views
3

Прошу прощения, если это дубликат. Пожалуйста, укажите правильный вопрос.C#: список сортировки по пользовательскому свойству

У меня есть класс с именем 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 EventId{get;set;} 
    public MyDate StartDate{get;set;} 
} 

У меня есть коллекция MyEvent как

List<MyEvent> myEvents. 

Теперь мне нужно сортируйте myEvents в порядке убывания StartDate. У меня проблема: я не могу добавить IComparable или изменить MyDate, так как он написан другой командой, и я просто ссылаюсь на dll. Я не имею контроля над кодом MyDate. Может ли кто-нибудь помочь мне, как я могу это сделать. Я создал новый класс сравнения, который реализует IComparer, но не может понять, как его использовать и сортировать myEvents.

** UPDATE 1 **

Большое спасибо Алексею, Ehsan и Дэйва за помощь мне. Я попробовал ответ Дейва, и это сработало. Я пытался сделать это более эффективно, так что нет необходимости добавлять новые свойства. Я не пытался использовать Ehsan для использования StringDateComparer, но это помогло мне понять, как я могу использовать выражения Comparer в Order linq. Наконец, как отметил Алексеем я, как показано ниже

** UPDATE 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 
        } 
      ); 
+0

это не точная копия, сценарий OP отличается –

+2

Класс, который принимает 'DateTime' преобразует в' SqlDateTime' и только выставляет на 'строки '? Ваша настоящая проблема - это другая команда. – juharr

+0

Вы, очевидно, видели, что я считаю [дубликат] (http://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object) вас вопрос, так как он сначала ссылается на поиск заголовка вашего сообщения (https://www.bing.com/search?q=C%23+%3A+Sort+list+on+custom+property). Пожалуйста, уточните, почему предлагаемые там решения не работают (включая пользовательский сопоставитель), поэтому ясно, что этот пост не дублируется. –

ответ

3

Это может быть неэффективным, но вы можете добавить DateTime свойство вашего MyEvent класса, который преобразует StartDate в DateTime и сортировать на что:

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); 

В качестве альтернативы, вы можете сделать класс неизменны и выполнить преобразование при инстанцировании его:

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; } 
} 
+1

но было бы установить свойство 'MyStartDate' при создании' MyEvent' и сделать 'MyEvent' неизменным .. – juharr

+0

Большое спасибо. Я попробовал, и это сработало. Я пытался сделать это более эффективно, так что нет необходимости добавлять какие-либо новые свойства. – Ziggler

3

Вы можете написать его с 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()); 
+0

Большое спасибо. Я не пробовал это, но это помогло мне понять, как я могу использовать команды сравнения в инструкции Linq – Ziggler

Смежные вопросы