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:
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...
TKipp
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.
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.
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;
}
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;
TKipp
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).