Autor Beitrag
RalphHoffmann
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Mo 13.04.15 09:53 
Hallo und guten Morgen liebe C# - Gemeinde :-)

Ich sitze hier an einer Übungsaufgabe, in der ich in einem Struct-Array eine BinarySearch durchführen soll. Ich habe das hier
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
//Array nach ID sortieren
Array.Sort<kiste>(akiste, (x, y) => string.Compare(x.ID, y.ID));

//Nach Inhalt von tmp_ID suchen
int i = Array.BinarySearch<kiste>(akiste, (y,x) => string.Compare(y.ID, x.ID));


Das Sortieren klappt wunderbar. Die Suche mag der Compiler aber nicht wirklich ;-). Ich habe mir entsprechende Artikel auf MSDN (msdn.microsoft.com/d...%28v=vs.110%29.aspx) durchgelesen werde daraus aber auch nicht schlauer, zumal dort nur eindimensionale Arrays angesprochen werden.

Ich verstehe z.B. auch nicht die Definition dort nicht: Was ist, oder macht die IComparable-Schnittstelle?

Weiß da jemand Rat....und vor allem: Kann mir jemand ein gutes C# Buch empfehlen?

Gruß
Ralph

Moderiert von user profile iconTh69: Topic aus C# - Die Sprache verschoben am Mo 13.04.2015 um 12:02


Zuletzt bearbeitet von RalphHoffmann am Di 09.06.15 12:50, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 13.04.15 12:20 
Hallo,

beim Array.Sort-Aufruf benutzt du diese Überladung Array.Sort<T>-Methode (T[], Comparison<T>) (also nicht die mit der IComparer-Schnittstelle). Für BinaraySearch gibt es aber keine entsprechende Überladung, sondern nur die per IComparer.

Um diese zu verwenden, müßtest du eine eigene Klasse erzeugen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
public class MyComparer : IComparer
{
   public int Compare(object x, object y)
   {
     // ...
   }
}

(oder gleich als generische Variante IComparer<T>) - s.a. IComparer.

PS: Du hast bisher auch nur ein eindimensionales Array (kiste) - hast dich wohl von x und y verwirren lassen?!
RalphHoffmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Do 16.04.15 07:32 
Hallo TH69,
ich verstehe nur Bahnhof.....

Ich habe jetzt eine Class eingerichtet:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
 public class Comparer : IComparer<string>
    {
        public int Compare(string x, string tmp_ID)
        {
            // Nach der gewünschten ID suchen
            return x.CompareTo(tmp_ID);
        }
    }


Für meinen Vergleich/meine Suche rufe ich das so auf:
ausblenden C#-Quelltext
1:
int i = Array.BinarySearch(akiste, tmp_ID, ID_c);					


Das will der Compiler auch nicht. Er meldet:
3-Argument: Kann nicht von "Einsendeaufgabe4.Comparer" in "System.Collections.IComparer" konvertiert werden.

Was ich dabei auch nicht verstehe ist, woher will die Class wissen, dass in akiste.ID gesucht werden muss? Und was heißt das mit dem Überladen?

Gruß
Ralph

ps.: Kannst Du mir ein Buch empfehlen, um c# leicht verständlich zu erlernen?

EDIT:
Ich habe noch ein wenig im Web gestöbert. Es ist wohl auch so, dass ich mein Struct Array, welche ich NICHT als Klassenvaribale deklarieren darf (so die Aufgabenstellung), nicht an eine andere Klasse übergeben kann. Ist ja auch logisch: Kennt die Class Comparer dieses Array ja auch nicht.

Es gibt aber noch eine Möglichkeit mittels Value Objects Daten von einer an eine andere Klasse zu übergeben....was es damit auf sich hat....keine Ahnung. Da bin ich erst einmal raus.....
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 16.04.15 09:57 
Deine Klasse implementiert IComparer<T> du hast eine Überladung der Binarysearch Methode verwendet die aber einen IComparer will.
Die Klasse weiß das sie in ID Suchen musst weil du die Klasse so implementieren solltest das sie die ID zum suchen benutzt.

Dein Comparer wird auf die Inhalte des Arrays angewendet und das sind kiste structs und keine strings. Du brauchst also eine Comparer (der das nicht generische IComparer Interface implementiert) für kiste structs nicht für strings bzw. einen für einen deiner structs und einen string. In diesem Comparer kannst du dann auf die ID zugreifen und die zum Vergleich benutzen.

Für diesen Beitrag haben gedankt: RalphHoffmann
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 16.04.15 10:01 
Hallo,

als Buch kann ich dir die OpenBooks Visual C# 2008 (noch mit WinForms und WPF) und Visual C# 2012 (nur noch mit WPF) empfehlen.

Im Kapitel 5.3.4 Die Elemente einer »ArrayList« sortieren gibt es Infos zur Verwendung der IComparable und ICompare-Schnittstelle (auch wenn man die Klasse ArrayList nicht mehr verwenden sollte, sondern stattdessen die generische List<T>).

Dein Aufruf müßte daher so aussehen:
ausblenden C#-Quelltext
1:
2:
string suchWert = "test";
int i = Array.BinarySearch(akiste, suchWert, new Comparer());

(sofern akiste ein string[] ist).

Für diesen Beitrag haben gedankt: RalphHoffmann
RalphHoffmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Do 16.04.15 12:50 
Hallo,
das Buch werde ich mir wohl mal anschaffen :-)

Das Problem ist, dass akiste _kein_ String, sondern ein Struct-Array ist. Darin soll ich drei float-Werte und einen String (eine ID, die nur einmal vergeben werden darf) hinterlegt werden.

Meine Verständnisschweirigkeiten fangen aber schon an den Unterschied zwischen IComparer, IComparer<T>, Comparer an. Was bedeutet das in vielen Befehlen zu lesende <T> zum Beispiel?

_oder_

Deine Klasse implementiert IComparer<T> du hast eine Überladung der Binarysearch Methode verwendet die aber einen IComparer will.

Da hätte Ralf auch Chinesisch mit mir reden können... ;-) Was bedeutet: Überladung? Ich verstehe dies so, dass ich eine Funktion/einen Befehl bei Aufruf nicht mit zu vielen Parametern überladen darf....ich vermute aber, dass ich damit total daneben liege.

Gruß
Ralph
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 16.04.15 13:07 
Das von @TH69 empfohlene Buch behandelt auch das Thema Generics (übrigens gleich das Folgekapitel zu dem verlinkten Kapitel) da kannst du nachlesen was es mit <T> auf sich hat. Für die Lösung dieser Aufgabe sind die nicht notwendig kannst du also eigentlich erstmal ignorieren. Die sollten dann in einer späteren Übungsaufgabe kommen.

Der Begriff Überladen bezieht sich auf den Methodennamen. Eine Klasse kann Methoden haben die sich im Namen nicht unterscheiden aber unterschiedliche Parameter haben. Diese Methode (eigentlich Methoden) nennt man dann überladen oder die Überladungen dieser Methode (sprachlich tut man so als wäre es eine Methode es sind aber mehrere die einfach nur gleich heißen) . Von Array.BinarySearch gibt es nun mehrere Überladungen und keine der Methoden die zu dem Methodennamen passen paßt zu den Parametern die du übergeben willst. Der Compiler hat dann in der Fehlermeldung die Überladung (die Methode mit passenden Namen aber unpassenden Parametern) genannt die am wenigsten nicht paßt (nach seiner Meinung, die tendenziell oft genug falsch ist).

Hoffe das ist jetzt weniger nah am chinesisch.

Edit: Ich sehe gerade das du in deinem ersten Beitrag schon Generics für das Sortieren verwendet hast. Wenn du nicht weiß was das ist solltest du die nicht verwenden. Es ist nicht Sinn von Übungsaufgaben Google bedienen zu lernen und gefundene Codeschnipsel zu benutzen damit die Aufgabe gelöst wird. Es geht darum Erkenntnisse über programmieren zu erlangen an denen du dich da eindeutig vorbei gemogelt hast.

Für diesen Beitrag haben gedankt: RalphHoffmann
RalphHoffmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Do 16.04.15 13:50 
Hallo Ralf,
Du hast Recht mit den Codeschnipseln und mit Google :-)

Dann verstehe ich nicht, dass solch eine Aufgabe zum jetzigen Zeitpunkt kommt. Kern der aufgabe ist es, den Umgang mit
1.) Arrays (auch Struct Arrays)
2.) Array.Sort und Array.BinarySearch und
3.) den allgemeinen Umgang mit Variablen und deren Übergabe an Methoden zu erlernen.

So weit, so gut. Das Ziel der Aufgabe ist eine 'Lagerverwaltung' für 50 Kisten zu schreiben. Die Daten über Länge, Breite, Höhe, Volumen und ID, sollen im Struct Array hinterlegt werden. Die ID darf nur einmal vorkommen.

Ich habe die aufgabe fertig, allerdings verwende ich bei der Kontrolle, der ID nicht Array.BinarySearch, sondern einfach eine for - Schleife und string.Compare. das funktioniert bestens. Bei 50 Elemten auch schnell. Wenn ich jedoch mit wesentlich größeren Datenmengen arbeite.... :-$

Ich werde die Aufgabe so, wie sie jetzt ist abgeben und mal den Fernlehrer fragen.

Gruß
Ralph
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 16.04.15 14:00 
Sowohl Array.Sort als auch Array.BinarySearch haben eine Überladung für IComparer. Du hast zwar eine andere Version von Sort benutzt die auch funktioniert aber dann wohl nicht den Weg benutz der im Sinne dieser Aufgabe gewünscht war.

Ich würde dir empfehlen einen Klasse mit IComparer Interface zu implementieren für die Sort Methode. Diese Klasse im Stil wie von TH69 gezeigt und dann versuchen diese IComparer Klasse auch für Binary Search zu verwenden. Da wirst du dann vielleicht über kleiner Details fallen und eventuell doch eine 2.te IComparer Klasse schreiben wollen aber die Erkenntnis solltest du erstmal selber sammeln. Und dann im Zweifel hier wieder nachhaken.

Für diesen Beitrag haben gedankt: RalphHoffmann
RalphHoffmann Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Do 16.04.15 16:12 
Hi Ralf,

so solls geschehen :-) Im Ernst....ich bin jetzt gerade im Job und habe hier leider keine Möglichkeit zu programmieren. Ich werde es versuchen über die Klassen zu schaffen. Da ist jetzt mein Ehrgeiz geweckt.

Ich werd' mich wieder melden.....

Beste Grüße
Ralph

und vielen Dank für die Hilfe und die Tipps!