2016-08-04 28 views
1

mit habe ich die folgenden Klassen-Hierarchie:C# - Liste sortieren <SomeClass> durch benutzerdefinierte CompareTo Methode

abstract class Product : IComparable 
{ 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    public string Barcode { get; set; } 

    public int CompareTo(object obj) 
    { 
     int ret = -1; 
     if (String.Compare(this.GetType().Name, obj.GetType().Name,StringComparison.Ordinal) == 0) 
      ret = 0; 

     return ret; 
    } 
} 

abstract class Book : Product 
{ 
    public int PagesCount { get; set; } 
} 

class ProgrammingBook : Book 
{ 
    public string ProgrammingLanguage { get; set; } 
} 

class CulinaryBook : Book 
{ 
    public string MainIngridient { get; set; } 
} 

class EsotericBook : Book 
{ 
    public int MininumAge { get; set; } 
} 
    abstract class Disc : Product 
{ 
    internal enum Content 
    { 
     Music, 
     Video, 
     Software 
    } 

    public Content DiscContent { get; set; } 
} 

class CdDisc : Disc 
{ 

} 

class DvdDisc : Disc 
{ 

} 

Und ich versuche folgende Sammlung zu sortieren, indem IComparable-Schnittstelle Methode CompareTo mit:

List<Product> products = new List<Product> 
     { 
      new DvdDisc {Name = "The lord of the rings 2",DiscContent = Disc.Content.Video,Price = 200M,Barcode = "5435443-2"}, 
      new CdDisc {Name = "Antonio Vivaldi: best picks",Price = 700M, DiscContent = Disc.Content.Music,Barcode = "4543765-565"}, 
      new CulinaryBook{Name = "Midterranian foods",MainIngridient = "Salmon",PagesCount = 436,Price = 350M,Barcode = "41457561-897"}, 
      new CdDisc{Name = "Windows XP", DiscContent = Disc.Content.Software, Price = 950M, Barcode = "5433668-4"}, 
      new EsotericBook{Name = "Russian Freemasonry 1731-2000",MininumAge = 21,PagesCount = 2100,Price = 3000M,Barcode = "6464632-876"}, 
      new CdDisc {Name = "The best of Mussorgsky",Price = 300M, DiscContent = Disc.Content.Music,Barcode = "5435436-567"}, 
      new ProgrammingBook{Name = "CLR via C#",PagesCount = 900, Price = 1110M,ProgrammingLanguage = "C#",Barcode = "5546533-2446"}, 
      new DvdDisc {Name = "The lord of the rings 1",DiscContent = Disc.Content.Video,Price = 200M,Barcode = "54354423-2"}, 
      new ProgrammingBook{Name = "ASP.NET MVC 4",PagesCount = 800,Price = 1200M,ProgrammingLanguage = "C#",Barcode = "46476573-65"}, 
      new EsotericBook{Name = "Russian Freemasonry in it's future and past",MininumAge =19, PagesCount = 900, Price = 2342M,Barcode = "3656353-24"}, 
      new CulinaryBook{Name = "Traditional Polish dishes",MainIngridient = "Red meat",PagesCount = 630,Price = 840,Barcode = "54634234-5"} 
     }; products.Sort(); 

Ausgabeliste sollte so aussehen:

1.1 Programmierbücher
1.2 Kulinarische Bücher

Meine aktuelle CompareTo Methode funktioniert nur ein Teil der Arbeit1.3 esoterische Bücher

2.1 CD-Discs von Inhalt
2.2 DVD sortierte Discs nach Inhalt sortierte - Klassen mit Namen zu vergleichen.

+1

Da Sie eine benutzerdefinierte Sortierung wünschen, wäre eine Option, der Produktklasse eine zusätzliche Eigenschaft hinzuzufügen und danach zu sortieren (z. B. Bücher programmieren - SortId = 0, Kulinarische Bücher SortId = 1, ...). –

Antwort

1

Dies ist ein funktionierendes Beispiel, die exakt gleiche Leistung übertragen wird:

1.1 Programming books 
1.2 Culinary books 
1.3 Esoteric books 

2.1 Cd discs sorted by content 
2.2 DVD discs sorted by content 

enter image description here

ich auch IComparable<Product> hinzugefügt leichter zu machen, vergleichbar mit anderen Produkten.

abstract class Product : IComparable<Product> 
    { 
     public string Name { get; set; } 
     public decimal Price { get; set; } 
     public string Barcode { get; set; } 
     protected abstract int InternalSortOrder { get; } 
     protected virtual string SortBy { get {return Name;} } 


     public int CompareTo(Product obj) 
     { 
      var sameType = string.Compare(GetType().Name, obj.GetType().Name, StringComparison.Ordinal) == 0; 

      var sameBaseType = GetType().BaseType != null && obj.GetType().BaseType != null && 
           string.Compare(GetType().BaseType.ToString(), obj.GetType().BaseType.ToString(), 
            StringComparison.Ordinal) == 0; 


      // They have the same base type, but not the same type. Order by base type first. 
      if (!sameType && !sameBaseType && GetType().BaseType != null && obj.GetType().BaseType != null) 
      { 
       // Order by base type first. 
       return string.Compare(GetType().BaseType.ToString(), obj.GetType().BaseType.ToString(), 
        StringComparison.Ordinal); 
      } 

      // it's the same base type (eg. book or disc) 
      if (sameBaseType) 
      { 
       // Order by sort order. 
       if (obj.InternalSortOrder != this.InternalSortOrder) 
       { 
        return InternalSortOrder.CompareTo(obj.InternalSortOrder); 
       } 
      } 

      if (sameType) 
      { 
       // Same sort order. We sort by name. 
       return string.Compare(SortBy, obj.SortBy, StringComparison.Ordinal); 
      } 

      // Order by Type. 
      return string.Compare(GetType().Name, obj.GetType().Name, StringComparison.Ordinal); 
     } 

    } 

    abstract class Book : Product 
    { 
     public int PagesCount { get; set; } 
    } 

    class ProgrammingBook : Book 
    { 
     public string ProgrammingLanguage { get; set; } 

     protected override int InternalSortOrder 
     { 
      get { return 1; } 
     } 
    } 

    class CulinaryBook : Book 
    { 
     public string MainIngridient { get; set; } 

     protected override int InternalSortOrder 
     { 
      get { return 2; } 
     } 
    } 

    class EsotericBook : Book 
    { 
     public int MininumAge { get; set; } 

     protected override int InternalSortOrder 
     { 
      get { return 3; } 
     } 
    } 
    abstract class Disc : Product 
    { 
     internal enum Content 
     { 
      Music, 
      Video, 
      Software 
     } 

     protected override string SortBy 
     { 
      get { return DiscContent.ToString(); } 
     } 

     public Content DiscContent { get; set; } 
    } 

    class CdDisc : Disc 
    { 
     protected override int InternalSortOrder 
     { 
      get { return 1; } 
     } 
    } 

    class DvdDisc : Disc 
    { 
     protected override int InternalSortOrder 
     { 
      get { return 2; } 
     } 
    } 

UPDATE:

Ich habe virtualSortBy in Product hinzugefügt. Es wird standardmäßig auf Name gehen, aber Disc wird Content zurückgeben.

+0

Mein schlechtes. Habe es komplett verpasst. Ich habe meine Antwort mit einem virtuellen SortBy in Produkt aktualisiert. Es sollte das Problem lösen. – smoksnes

+0

Wow! Meine Lösung für dieses Problem ist viel schlimmer. Vielen Dank. –

+0

Ich bin nicht stolz auf die vielen wenn Fälle. Aber es funktioniert. – smoksnes

1

Sie müssen sich mit gleich

Option
rtn = Primary Sort; 
if(rtn =0) 
    rtn =secondary Sort; 
if(rtn =0) 
    rtn =tertiary Sort; 

als primäre Art auf der Art des Buches zu sein scheint

Sie

rtn = this.GetType().Name.CompareTo(obj.GetType().Name); 
if(rtn ==0) 
    rtn =this.Name.CompareTo(obj.Name); 
return rtn; 

wenn Ihr Problem ist, dass Sie ist tun würde, arbeiten möchte keine alphabetische Sortierung nach Typ dann zu Produkt hinzufügen

public abstract int SortOrder{get;} 

und verwenden, die als primäre Art