myCSharp.de - DIE C# und .NET Community (https://www.mycsharp.de/wbb2/index.php)
- Entwicklung (https://www.mycsharp.de/wbb2/board.php?boardid=3)
-- Grundlagen von C# (https://www.mycsharp.de/wbb2/board.php?boardid=88)
--- LINQ Expression zum Sortieren von Objekten wirft Exception aus (https://www.mycsharp.de/wbb2/thread.php?threadid=121755)


Geschrieben von TKipp am 06.04.2019 um 08:37:
  LINQ Expression zum Sortieren von Objekten wirft Exception aus
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:

Fehlermeldung:
"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:

C#-Code:
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:

C#-Code:
        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...


Geschrieben von dannoe am 06.04.2019 um 09:40:
 
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.


Geschrieben von T-Virus am 06.04.2019 um 09:48:
 
Vermutlich wolltest du noch die Property ReceiverName bei der orderby mitgeben :)

C#-Code:
receivers = (from item in receivers orderby item.Receiver.ReceiverName descending select item).ToList();


Geschrieben von Th69 am 06.04.2019 um 10:09:
 
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:

C#-Code:
int CompareReceivers(Receiver receiver1, Receiver receiver2)
{
  // compare
  return ...;
}

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

C#-Code:
public override string ToString()
{
     return Receiver?.ReceiverName;
}


Geschrieben von TKipp am 06.04.2019 um 14:00:
 
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.

C#-Code:
       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:

C#-Code:
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

C#-Code:
return  this.Receiver==null ? null : Receiver.ReceiverName;


Geschrieben von Th69 am 07.04.2019 um 08:58:
 
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).


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 23.02.2020 18:46