Hi,
ich habe folgende Frage:
Und zwar möchte ich ein globales Array erstellen (public static), welches ich dann später, wenn ich es verwende, als int oder string deklariere.
Ich habe mehrere Methoden die das Array verwenden (Sortieralgorithmen) und wahlweise int oder string-Werte sortieren sollen.
Da der Array-Name gleich bleiben soll muss der Typ entsprechend geändert werden können. Nur wie erstelle ich ein quasi 'void'-Array (als global und public static) so dass ich in einer Methode (in der überprüft wird, ob int oder string-Werte darin gespeichert werden sollen) sagen kann: "du bist jetzt ein int-Array" oder "du bist jetzt ein string-Array". Selbstverständlich bevor Daten darin gespeichert werden...
Danke für eure Hilfe
Jan
Hallo!
Mach doch ein object-array. Dann kannst du nachher abfragen, ob int-Werte oder strings darinstehen:
if (array[0] is int)
{ // integer }
else if (array[0] is string)
{ ...}
mfg
Mit nem object-Array habe ich es schon versucht, aber dann kann ich nicht mehr überprüfen ob z.B. (Array[0]<Array[1]). Deswegen wärs einfacher wenn ich ein void-Array erstellen könnte, dessen Typ ich je nach Wunsch zu int oder string ändern kann. Die Sortieralgorithmen funktionieren an sich schon (momentan ist der Typ fest auf int) und ich habe keine Lust die nochmal umprogrammieren zu müssen 🙂
Wenn der Array-Name gleich bleibt interessiert es den Sort-Algorithmus wenig obs ein string oder int Array ist...
du kannst ja innerhalb der sortier-methode auf ein int-array casten:
object[] werte = new object[10];
...
int[] intwerte = (int[])werte;
mfg
Auch das geht leider nicht, weil 2 Klassen zugriff auf das Array haben.
Eine Klasse speichert die Werte im Array und gibt das Array auf dem Bildschirm aus, die andere Klasse sortiert das Array schrittweise. Die Sortierklassen laufen als Threads ab, damit ich nach jedem Tauschvorgang das Array neu ausgeben kann (das ganze ist ein Projekt welches wir fürs 1. und 2. Semester zur anschaulichen Visualisierung von Sortieralgorithmen machen).
Das heisst Quasi:
-Zahlen oder strings in Array schreiben (Zeichnen-Klasse)
-Nächsten Sortierschritt ausführen(Sortier-Klasse)
Sortieralgorithmus anhalten
-Array grafisch ausgeben(Zeichnen-Klasse)
Bei Klick auf "Weiter"-Button Sortieralgorithmus fortsetzen
und das solange wie das Array noch nicht fertig ist und der Benutzer den "Weiter" Button anklickt. Deswegen kann ich kein zweites Array verwenden.
Hallo,
du kannst auch einfach die Arraywerte auf IComparable casten und mit CompareTo vergeleichen.
cu, tb
Für diesen Anwendungsfall gibt es generische Klassen.
z.B.: List<T>
Klingt für mich alles nach ungünstigen Programmdesign. Hört sich so an als wenn du das Array als globale Variable aus den Funktionen benutzt. Das ist nicht wirklich gut.
Übergib doch der Sortierfunktion das Array als IComperable, weil das implementieren sowohl int als auch string. In deiner Funktion kannst du wie schon vorgeschlagen mit CompareTo vergleichen, je nach Sortieralgorithmus. Als Rückgabetyp hast du halt wieder nen IComparable Array und müsstest dir bei Aufruf in der Funktion halt merken ob es nen String oder nen Int war um die Rückgabe auswerten zu können. Da ja eh mit Referenzen gearbeitet wird, macht es keinen Unterschied ob auf das Array als globale Variable zugreifst oder als Übergabewert. Das wäre die Möglichkeit in .Net 1.1.
Die andere Lösung wurde auch schon genannt, indem du in .Net 2.0 die generischen Typen verwendest. Dort machst du im Prinzip auch nichts anderes als CompareTo zu verwenden, nur das du dort halt mit T als Typ arbeiten kannst, statt das Array auf IComparable zu casten.
Was beide Arten betrifft, würd ich das mit jeweils den nächsten Schritt mit ner einfachen boolschen Variablen machen. So in der Art:
<T> Sortierfunktion {
if(naechsterSchritt) {
// eigentlicher Sortieralgo
naechsterSchritt = false;
}
}
Wobei naechsterSchritt als private Klassenvariable realisiert ist, die du beliebig auf false oder true setzen kannst. Nun kannst du praktisch immer Schrittweise sortieren.
Naja, so einfach ist das mit dem Sortieren nicht. Dadurch, dass sich der Quicksort rekursiv aufruft, kann ich nicht mittendrin per return rausspringen, sondern wie gesagt lasse ich den als Thread laufen, den ich mit Suspend pausieren lasse. Deswegen auch das Globale Array. Und was das Programmdesign anbetrifft, wir machen das als Projekt in Software Engeneering, da ist dann die Programmstruktur schon in gewissem Maße vorgegeben...
Aber kann man das Problem nicht per Vererbung lösen? Also das ich z.B. in der class xyz das Array ohne Typ erstellen kann, und dann in "class SortString: xyz" das Element auf string festlege und in der "class SortArray: xyz" auf int?
Auf jeden Fall schonmal vielen Dank für eure bisherigen und zukünftigen Bemühungen 🙂
Hallo Satanlike,
wenn man denselben Algorithmus für verschiedene Datentyen verwenden will, gibt es m.E. genau zwei Lösungen:
Wobei mir Generics in deinem konkreten Fall besser geeignet scheinen.
herbivore
hat das .net framework da nich schon was, was den datentyp automatisch wählt für nen array? ich mein da was gesehen zu haben.... 🤔
Hallo Afrokalypse,
falls du das meinst: C# 2.0 bietet Unterstützung für Generics. Und das .NET 2.0 Framework enthält generische Klassen, wie das oben angesprochene List<T>.
herbivore
Original von Afrokalypse
hat das .net framework da nich schon was, was den datentyp automatisch wählt für nen array? ich mein da was gesehen zu haben.... 🤔
Was du eventuell noch meinen könntest ist aus der C# 3.0 Preview der Datentyp var. Der ist aber auch nicht wirklich dafür geeignet, im Endeffekt würde es nämlich auch darauf hinauslaufen dass du mit den Interfaces arbeiten musst, weil du ja net weißt welchen Datentyp var hat, bzw. wie er sich sortieren lässt.
Das mit den generics hört sich gut an, kann mir da jemand vllt sagen, wo man ne gute einführung dazu findet?
Ich werd mir dann auch noch das .net framework 2.0 draufmachen müssen, hab aktuell nur das 1.1er 🙂
Hallo Satanlike,
gut ist immer relativ, aber die offizielle Einführung findet sich natürlich in der SDK-Doku:
General Reference/Languages and Compiler/C#/C# Programmer's Reference/C# Programming/Generics
herbivore
Und ich möchte noch einmal unterstreichen, was beiläufig gesagt wurde:
Verwende IComparable[] als Typ für deine zu sortierenden Werte. Sortier-Algorithmen kann man schließlich nur auf sortier- bzw. vergleichbare Typen anwenden (oder man liefert explizit einen IComparer, der die Entscheidung fällt mit).
In der Regel sparst du dir dann sämtliche Casts, da du grundsätzlich immer nur die IComparable.CompareTo Methode verwenden musst und dein Sortieralgorithmus dann auch ziemlich automatisch für alle Objekte gilt, die IComparable implementieren, ohne dass du auch nur einen Finger rühren musst 😉
So mal als Pseudo-Code auf das Essentielle gekürzt:
/* Sortiermethoden */
public void Sort(IComparable[] to_sort); /* Sortierung durch IComparable.CompareTo(obj2) */
public void Sort(object[] to_sort, IComparer comparer); /* Sortierung durch IComparer.Compare(objA, objB); */
Das heißt, statt "int [] Array..." oder "string [] Array" mach ich einfach ein "IComparable [] Array", in das ich dann alles mögliche reinschreiben kann (solange die Werte natürlich vergleichbar sind)?
edit: und wie in etwa funktioniert das mit dem CompareTo, ich hab das bisher nicht verwendet...
Hallo Satanlike,
nein, mach das nicht so. So müsstest du damit klar kommen, dass String und int in dem Array gemixt vorkommen. Macht nur Probleme. Nimm Generics.
herbivore
als einführung find ich den webcast Generics mit C# gut:
http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=118757741
Also ich hab das mit IComparable gelöst... Geht absolut problemlos, v.a. weil der Benutzer auswählt, ob ints oder strings sortiert werden sollen...
Aber eine andere Frage habe ich noch: Der aktuelle Sortieralgorithmus läuft als Thread, damit ich mit Suspend unterbrechen kann. Wenn ich jetzt aber Thread.Abort mache, kann ich den Thread nicht neustarten... Gibts dafür vllt ein Workaround?
Ein Blick in die Doku wäre halt auch eine gute Idee 🤔
Thread.Abort
Calling this method usually terminates the thread.
Noch Fragen ?
PS: Falls Dir terminieren kein Begriff ist, dann Guckst Du: Terminator mit Arni Schwabbelegger
Ja, denn so habe ich es nicht gemeint...
Und zwar, wenn ich den Thread mit Abort abbreche, wie kann ich ihn dann neustarten? Mit xyz.Start() geht es nämlich nicht, da "der Thread noch läuft oder abgebrochen wurde"...
Hallo Satanlike,
gut, dann noch mal Klartext. Du kannst den Thread nicht neu starten.
herbivore
Ok, so weit habe ich das auch schon bemerkt. Kann ich aber nicht die Instanz des Threads löschen und eine neue erstellen?
Hallo Satanlike,
ja, kannst du. 🙂
herbivore
Muss man euch alles aus der Nase ziehen ?(
Was ist denn das Gegenteil von new?
Hallo Satanlike,
old?
Im Ernst: am ehesten Dispose. Gibt es aber bei Thread nicht. Also kann und muss man es nicht aufrufen.
Erzeug also einfach ein neues Objekt. Der GarbageCollector mach den Rest.
herbivore
Ja, sowas habe ich mir schon gedacht, nur dass ich, wenn ich einen neuen Thread erzeuge einen anderen Namen wählen muss... Aber ein Thread-Array sollte genügen 😁
Hallo Satanlike,
was meinst du mit neuen Namen? Einen neuen Variablennamen? Das musst du nicht. Und auch Thread.Name muss m.E. nicht eindeutig sein.
herbivore
Also wenn ich einen "Thread xyz = new Thread....." erstelle, kann ich xyz, nachdem der Thread beendet wird, nicht nochmals verwenden. Hab da schon diverse Versuche gestartet, aber nichts hat funktioniert. Habe deshalb ein Array aus Threads erstellt, in dem allerdings immer nur ein Thread läuft und auf den nächsten imm Array übergeht, falls der vorherige beendet wurde. So funktioniert es nun absolut problemlos...
Hallo Satanlike,
folgendes geht wirklich nicht:
Thread xyz = new Thread(blablubb);
xyz.Start();
xyz.Abort();
xyz = new Thread(blablubb);
// ...
?
Ciao
Norman-Timo
Also ich kann problemlos die Thread-Variable wiederverwenden... weiss nicht wieso das bei Dir norman_timo nicht geht....
Aber insgesamt ist das abschiessen eines Threads immer eine unschöne Angelegenheit und in der Regel völlig unnötig.
Siehe folgendes Beispiel:
using System;
using System.Threading;
namespace ThreadRestart
{
public class Work
{
private volatile bool _IsWorking=false;
public Work()
{
}
public void EntryPoint()
{
//Der Thread wurstelt solange rum wie _IsWorking true ist
this._IsWorking=true;
do
{
//simuliere Workload
System.Diagnostics.Debug.WriteLine("Still working");
Thread.Sleep(100);
}while(this._IsWorking);
}
/// <summary>
/// Diese Methode stoppt den Thread und wartet bis dieser abgelaufen ist
/// somit BLOCKT diese Methode !!
/// </summary>
/// <param name="pThreadToStop">den zu stoppenden Thread</param>
public void StopThread(Thread pThreadToStop)
{
//das Flag so setzen dass der Thread beim nächsten Durchgang ausläuft
this._IsWorking=false;
//warte auf den Thread
pThreadToStop.Join();
}
}
}
Aufrufender Code:
private void button1_Click(object sender, System.EventArgs e)
{
Work w=new Work();
Thread thr=new Thread(new ThreadStart(w.EntryPoint));
thr.Name="Worker";
thr.Start();
//mal ein wenig schlafen
Thread.Sleep(10000);
//blockiere bis der Thread tot ist
w.StopThread(thr);
//neuen Thread erstellen und starten (mit selber Variable)
thr=new Thread(new ThreadStart(w.EntryPoint));
thr.Name="Worker";
thr.Start();
Thread.Sleep(10000);
w.StopThread(thr);
thr=null;
}
Ist doch viel schöner Threads auslaufen zu lassen
Danke Programmierhans. Ich glaube meinen Fehler gefunden zu haben, ich habe wohl beim erneuten erstellen "Thread xyz = new..." statt " xyz = new...". Jetzt funktioniert alles auch ohne Arrays. Auch mit den Arrays habe ich kein Abort benutzt, sondern den Thread auch zuende laufen lassen.
Hallo Programmierhans,
weiss nicht wieso das bei Dir norman_timo nicht geht....
norman_timo hatte die Frage gestellt, ob es bei Satanlike wirklich nicht geht. Er keine Aussage gemacht.
herbivore
Hallo zusammen,
ich hatte vermutet, dass Satanlike 2x 'Thread xyz = new ...' verwendet hatte, und Herbivore hatte recht, ich hab das nur als Frage gestellt.
Vielleicht ein bissl blöd von mir formuliert...
Ciao
Norman-Timo
Original von norman_timo
Hallo zusammen,ich hatte vermutet, dass Satanlike 2x 'Thread xyz = new ...' verwendet hatte, und Herbivore hatte recht, ich hab das nur als Frage gestellt.
Vielleicht ein bissl blöd von mir formuliert...
Ciao
Norman-Timo
😉 gut haben wir darüber gesprochen ..