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
LINQ Expression zum Sortieren von Objekten wirft Exception aus
TKipp
myCSharp.de - Member



Dabei seit:
Beiträge: 18
Herkunft: Berlin

Themenstarter:

LINQ Expression zum Sortieren von Objekten wirft Exception aus

beantworten | zitieren | melden

Hallo Leute,
folgender Code soll eingentlich die von einem Webservice gelieferten Objekte, die über eine Combobox ausgelesen werden, sortieren. Tut es aber nicht. Anstatt dessen bekomme ich die Exception:
Fehler
"mindestens ein Objekt muss IComparable implementieren"
Was ist da los? Was läuft falsch? wie geht's richtig?
Hier zunächst der Code der Klasse, welches die Objekte liefert:


using System;
using System.Collections.Generic;
using System.Text;
using ControlExpert_PostMaster.PostMasterWs;

namespace ControlExpert_PostMaster
{
    /// <summary>
    /// Container class for Receiver from WSDL with overwritten ToString() method.
    /// Note: Not inherited, because then the object is not applicable to the WSDL-object without cast etc.
    /// </summary>
    public class AmsReceiver
    {
        public Receiver Receiver { get; set; }

        public override String ToString()
        {
            if (this.Receiver != null)
            {
                return Receiver.ReceiverName;
            }
            else
            {
                return null;
            }
        }
    }
}

und hier der Code, dessen LINQ statement besagte Exception auswirft:


        private void setReceivers() {
            this.cmbReceiver.SelectedIndexChanged -= this.cmbReceiver_SelectedIndexChanged;
            //TKipp/27.03.2019/Sort Receiver in alpabetical order
            List<AmsReceiver> receivers=new List<AmsReceiver>();
            if(this.transactionData.Receivers != null) {
                receivers.AddRange(this.transactionData.Receivers);
                receivers = (from item in receivers
                                               orderby item.Receiver descending
                                               select item).ToList();

                this.cmbReceiver.DataSource = receivers;
            } else
                this.cmbReceiver.DataSource = this.transactionData.Receivers;
            //TKipp/27.03.2019/End of sorting

            this.cmbReceiver.SelectedIndex = -1;
            this.cmbReceiver.SelectedIndexChanged += this.cmbReceiver_SelectedIndexChanged;
        }
Die Objekte sind lt.Debugger mittels AddRange in die Liste eingefügt worden, werden allerdings nicht sortiert, da das LINQ statement fehlerhaft ist...
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von TKipp am .
TKipp
private Nachricht | Beiträge des Benutzers
dannoe
myCSharp.de - Member



Dabei seit:
Beiträge: 174

beantworten | zitieren | melden

Woher soll die Sortiermethode denn wissen, nach welcher Logik du sortieren möchtest?
Du übergibst lediglich das Property Receiver von AmsReceiver und der Typ Receiver hat anscheinend keine IComparable-Schnittstelle, somit gibt es auch keine Sortierlogik.
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1837
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Vermutlich wolltest du noch die Property ReceiverName bei der orderby mitgeben :)


receivers = (from item in receivers orderby item.Receiver.ReceiverName descending select item).ToList();
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4028

beantworten | zitieren | melden

Ist Receiver eine Klasse von dir?
Ansonsten kannst du mittels eine der List.Sort()-Methoden (ohne LINQ) das Sortieren durchführen - am einfachsten selber eine Comparison<T>-Methode erstellen, welche dann -1, 0 oder 1 zurückliefert:


int CompareReceivers(Receiver receiver1, Receiver receiver2)
{
  // compare
  return ...;
}

Und noch als Hinweis:
die ToString-Methode kannst du verkürzen zu


public override string ToString()
{
     return Receiver?.ReceiverName;
}
private Nachricht | Beiträge des Benutzers
TKipp
myCSharp.de - Member



Dabei seit:
Beiträge: 18
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Receiver ist eine Klasse des Webservices, der mir die Objekte liefert.
Folgender Code funktioniert, d.h., er sortiert die Objekte in alphabetischer Reihenfolge ohne, wie bisher eine Exception auszuwerfen.


       private void setReceivers() {
            this.cmbReceiver.SelectedIndexChanged -= this.cmbReceiver_SelectedIndexChanged;
            //TKipp/27.03.2019/Sort Receiver in alpabetical order
            AmsReceiver ams = new AmsReceiver();
            List<AmsReceiver> receivers = new List<AmsReceiver>();
            if(this.transactionData.Receivers != null) {
                receivers.AddRange(this.transactionData.Receivers);
                receivers.Sort((item1, item2) => item1.Receiver.ReceiverName.CompareTo(item2.Receiver.ReceiverName));
                this.cmbReceiver.DataSource = receivers;
            } else
                this.cmbReceiver.DataSource = this.transactionData.Receivers;
            //TKipp/27.03.2019/End of sorting

            this.cmbReceiver.SelectedIndex = -1;
            this.cmbReceiver.SelectedIndexChanged += this.cmbReceiver_SelectedIndexChanged;
        }
Dasselbe kürzer:


 List<AmsReceiver> receivers = (from item in this.transactionData.Receivers
                                                   orderby item.Receiver.ReceiverName ascending
                                                   select item).ToList();

Danke für den Tipp, den Code verkürzen zu können. Allerdings benutze ich ternäre Operatoren nur ungerne.Ist folgender Ausdruck äquivalent zu Deinigem


return  this.Receiver==null ? null : Receiver.ReceiverName;
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von TKipp am .
TKipp
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4028

beantworten | zitieren | melden

Ja, dein ToString()-Code ist (semantisch) identisch zu meinem.
Jedoch verwendest gerade du den ternären Operator ? : (denn dieser verwendet ja 3 Teilausdrücke ;-). Dafür wurde ja gerade der ?.-Operator eingeführt, um die Abfrage auf null nicht immer ausschreiben zu müssen (vermeiden sollte man aber Kaskaden von ?.-Abfragen in einem längeren geschachtelten Ausdruck).
private Nachricht | Beiträge des Benutzers