Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Bubblesort mit generics
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

Bubblesort mit generics

beantworten | zitieren | melden

Hallo Forum!

Ich programmiere mittlerweile auf Arbeit eine Menge und stelle immer wieder fest, das man den ein oder anderen Algorithmus, den man im Studium gelernt hat auch dort wieder verwenden kann.
Nun hab ich gedacht, ich schreibe mir eine Klasse, die diese Algorithmen umfasst.
Ich wollte genauso schön einfach, wie im Studium auch, zunächst mit dem Bubblesort anfangen.
Damit er nicht Typen abhängig ist, habe ich gedacht ich schreibe ihn mit einem generic.
Das ganze sieht dann so aus:


public static void BubbleSort<typ>(typ[] feld)
{
    int nr =0;
    bool sort;
    typ tmp;
    do
    {
        sort = true;
        for (int i = 0; i < feld.Length - nr; i++)
        {
            if (feld[i] > feld[i + 1])                          //<- Fehler
            {
                sort = false;
                tmp = feld[i + 1];
                feld[i + 1] = feld[i];
                feld[i] = tmp;
             }
         }
         nr++;
    } while (!sort);
}
Nun habe ich festgestellt, das beim größer Vergleich ein Fehler auftritt.
Der Operator ">" kann nicht auf Operanden vom Typ "typ" und "typ" angewendet werden.
Kann mir da jemand helfen, das zu umgehen?

Würde mich sehr freuen. Besten dank schon mal.
private Nachricht | Beiträge des Benutzers
Andavos
myCSharp.de - Member



Dabei seit:
Beiträge: 138

beantworten | zitieren | melden

Hallo,
du musst typ auf Typen einschränken, die das Interface IComparable implementieren, denn beliebige Objekte lassen sich nicht vergleichen bzw. sortieren ([1]).
Dies geht dann mit where:
BubbleSort<typ> where typ : IComparable
(ich weiß nicht ob es auch mit static Methoden so geht)

Dann statt > oder o.ä. muss du ((IComparable)object).CompareTo() verwenden.



[1] Hat man z.B. eine Klasse für die komplexen Zahlen, dann lassen sich diese nicht (sinnvoll/eindeutig) sortieren, da die komplexen Zahlen nicht geordnet sind.
Ebenso kann man sehr sehr komplexe Objekte nur schwer sortieren.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Andavos am .
private Nachricht | Beiträge des Benutzers
kleines_eichhoernchen
myCSharp.de - Member

Avatar #avatar-2079.jpg


Dabei seit:
Beiträge: 3.971
Herkunft: Ursprünglich Vogtland, jetzt Much

beantworten | zitieren | melden

Generics sind leider nicht im Vergleich zu C++ Templates stark in Ihren Möglichkeiten eingeschränkt. Entweder du machst es wie Andovos beschreibt, mit den ICompareable oder du machst deine Helper-Klasse abstract und implementierst eine Funktion zum Vergleichen, die entsprechend implementiert werden muss.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
private Nachricht | Beiträge des Benutzers
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Wow das ging ja echt schnell.
Ich werd es mal versuchen. Vielen dank!
private Nachricht | Beiträge des Benutzers
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Hallo!

Nach dem ich es gestern noch ausprobiert habe, will ich heute noch meine funktionsfähige Lösung präsentieren.
Ob das nun die beste Lösung ist, weiß ich nicht. Ich hätte eigentlich lieber die Methode anstatt der Klasse als generic, aber so funktioniert es erstmal ;-)


public class FabisAlgorithmen<typ> : IComparable<typ>
{
        
    int IComparable<typ>.CompareTo(typ t)
    {
        return ((IComparable)this).CompareTo(t);
    }

    public static void BubbleSort(typ[] feld)
    {
         int nr =1;
         bool sort;
         typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (((IComparable)feld[i]).CompareTo(feld[i + 1])>0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
              }
              nr++;
          } while (!sort);
     }
}

Sollte jemand noch einen Verbesserungsvorschlag haben, bin ich für alles offen.
Ansonsten hoffe ich, das es vlt jemanden den noch weiter hilft, den im Internet habe ich sonst zu dem Thema nicht alt so viel gefunden.

Einen schönen Sonntag an alle!
private Nachricht | Beiträge des Benutzers
GMLOD
myCSharp.de - Member

Avatar #avatar-2654.jpg


Dabei seit:
Beiträge: 1.200

beantworten | zitieren | melden

Du kannst auch auf die Methode eine Einschränkung setzen:

public static void BubbleSort<typ>(typ[] feld) where typ : IComparable
{
     //code
}
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von GMLOD am .
Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!
private Nachricht | Beiträge des Benutzers
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Stimmt, das ist noch viel besser!

Das war dass, was Andavos schon am Anfang meinte, ich bloß nicht richtig verstanden habe, bzw. aus unwissenheit nicht umgesetzt habe.

Viel Dank an alle!
private Nachricht | Beiträge des Benutzers
GMLOD
myCSharp.de - Member

Avatar #avatar-2654.jpg


Dabei seit:
Beiträge: 1.200

beantworten | zitieren | melden

Ist ja ok, wenn du durch die Implementierung deiner Algorithmen lernen willst. Aber denke dran, dass du, wenn du ein Produkt erstellen willst, besser auf Array.Sort zurückgreifst.
Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!
private Nachricht | Beiträge des Benutzers
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Ja die Methode habe ich auch kennengelernt, als ich nach dem Interface ICloneable gesucht habe.
Mir ging es auch mehr um andere Algorithmen als den Bubblesort. Der hat sich bloß als Anfangsbeispiel angeboten, weil man den nun schon einige male in verschiedenen Sprachen programmiert hat.

Dank eurer Hilfe habe ich aber wirklich einiges gelernt, also hat es sich aufjedenfall gelohnt, vielen dank nochmal ;-)
private Nachricht | Beiträge des Benutzers
zommi
myCSharp.de - Member

Avatar #avatar-2617.png


Dabei seit:
Beiträge: 1.361
Herkunft: Berlin

beantworten | zitieren | melden

Hi Zoomy,

vielleicht solltest du auch lieber

public static void BubbleSort<T>(T[] feld) where T: IComparable<T>
nehmen.

Mhh.. vielleicht sollte man auch der Konvention wegen den Typparameter immer in Großbuchstaben schreiben.

Ach und den Cast bei

if (((IComparable)feld[i]).CompareTo(feld[i + 1])>0)
kannst du dir so oder so sparen.

beste Grüße
zommi
private Nachricht | Beiträge des Benutzers
kleines_eichhoernchen
myCSharp.de - Member

Avatar #avatar-2079.jpg


Dabei seit:
Beiträge: 3.971
Herkunft: Ursprünglich Vogtland, jetzt Much

beantworten | zitieren | melden

Zitat
class FabisAlgorithmen<typ> : IComparable<typ>
IComparable gehört auch nicht in deine Hilfsklasse, sondern in die Klassen und Strukturen, die du sortieren willst. Viele Datentypen aus dem .NET Framework implementieren bereits diese Schnittstelle (Int32, Float, Double, Decimal, String, usw.) Bei eigenen Datentypen müsstest du die Schnittstelle entsprechend nachimplementieren.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
private Nachricht | Beiträge des Benutzers
Zoomy
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Hallo!

Hab eure Beiträge erst jetzt gesehen.

@kleines_eichhoernchen:
Nach dem Hinweis von GMLOD habe ich das so umgeschrieben. Habt ihr beide recht, das ist schöner.

@zommi
Mit dem Cast hast vollkommen recht. Ist mir vorher nicht aufgefallen.
Und wenn ich konsequent bin, muss ich den Typparameter auch groß schreiben.
Auch wenn "T" in der Literatur üblich ist, hab ich mich jetzt für "Typ" entschieden, weil ich es einfach noch lesbarer finde.
(P.S. übrigens schicker name;) und auch ich komme ursprünglich aus Berlin)

Danke euch beiden!

Mein Code sieht nun mittlerweile so aus:


public class FabisAlgorithmen 
{
    public static void BubbleSort<Typ>(Typ[] feld) where Typ : IComparable
    {
         int nr = 1;
         bool sort;
         Typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (feld[i].CompareTo(feld[i + 1]) > 0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
             }
             nr++;
        } while (!sort);
}

Übrigens will ich noch ein großes Lob an euch alle aussprechen. Im programmieren bin ich recht fit, allerdings programmier ich noch nicht sehr lange in .NET.
Und kenn deswegen viele Möglichkeiten noch nicht. Ihr habt mir alle geholfen ein bisschen besser hinterzusteigen;-)
private Nachricht | Beiträge des Benutzers
Peter Bucher
myCSharp.de - Experte

Avatar #jVxXe7MDBPAimxdX3em3.jpg


Dabei seit:
Beiträge: 5.940
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Hallo Zoomy

Wenn du nur ein Typparameter hast, solltest du ihn "T" benennen.
Bei mehreren Typparametern gilt dann eine abgeleitete Konvention, bspw.:


public static void Foo<TParameterOne, TParameterTwo>(TParameterOne bar) {
    // ...
}


Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

- https://peterbucher.ch/ - Meine persönliche Seite
- https://fpvspots.net/ - Spots für FPV Dronenflüge
private Nachricht | Beiträge des Benutzers