Ich hoffe das mir keiner mein Array als Stack auslegt.
Ein Stack, kein Zweifel.
Denn in der iMove-Schleife wird das Array am Ende mit
aiFrom [iDisk-1] = iTmp;
verändert. Ohne diese Zeile wäre es ok, denn du würdest ohne zusätzliche Zwischenspeicherstruktur - Stack, Array, was auch immer - auskommen.
Aber das Turm-von-Hanoi Problem ist wirklich ohne "rekursiven" Zwischenspeicher zu lösen. Laut Buneman und Levy (und Wikipedia) muss in jedem Schleifendurchlauf nur bekannt sein, wie gross die Scheiben auf den Türmen sind. Man braucht also immer nur die aktuellen Werte.
Zitat von Wikipedia
Ausführen bis der gesamte Turm verschoben wurde:
1. Die kleinste verschiebbare Scheibe auf den Stapel rechts von ihr legen
(bzw. auf den ersten, wenn die Scheibe auf dem letzten Stapel liegt).
2. Die zweitkleinste verschiebbare Scheibe auf den einzig möglichen Stapel verschieben.
// Factory instanziieren.
CommandFactory factory = new CommandFactory();
// Commands registrieren.
factory.RegisterCommand("Move", typeof(MoveCommand), new MoveParameters());
factory.RegisterCommand("Exit", typeof(ExitCommand), new ExitParameters());
// Move-Command erzeugen.
MoveCommand move = (MoveCommand)factory.CreateCommand("Move");
Resultat: jedes MoveCommand-Objekt bekommt die selbe MoveParameters-Instanz gesetzt, die SetParameters-Methode kann problemlos in der Basisklasse Command definiert werden, erneute Definition in den Command-Ableitungen ist nicht erforderlich.
Spricht doch nichts dagegen. Flexibler als eine statische Methode ist es auf jeden Fall (auf statische Methoden, die den Zustand der Klasse ändern, würde ich ohnehin immer verzichten wollen).
Du müsstest mal untersuchen wie es sein kann, dass zwei Sessions gleichzeitig offen sind. Vielleicht vergisst du irgendwo eine Session zu schliessen oder öffnest unbeabsichtigt eine neue.
Wenn es geht, sollte man vermeiden, mehrere Sessions parallel offen zu haben. Ist natürlich nicht immer möglich. Mit mehreren Sessions muss aber unbedingt sichergestellt werden, dass persistente Objekte nicht zwischen den Sessions wandern können.
Ich hatte dieses Problem mal im Zusammenhang mit "geschachtelten" Transaktionen. Innerhalb einer laufenden Transaktion sollte eine zweite durchgeführt werden, um Statusänderungen und Log-Meldungen in die Datenbank zu schreiben, damit diese auch bei einem Rollback der äußeren Transaktion erhalten bleiben.
Folgendes Szenario mit zwei Sessions/Transaktionen löste die Exception aus:
Status wieder speichern
Status laden |
| v
v [---]
[------------------------------]
Die Lösung sah bei mir so aus:
Status laden Status wieder speichern
| |
v v
[---] [---]
[------------------------------]
Falls das Datenmodell noch geändert werden kann, es gibt eine sehr elegante Möglichkeit Bäume in Tabellen abzubilden.
Hatte Noodles mir mal gezeigt, das Datendesign nennt sich "Nested Sets". Der grosse Vorteil: man kann mit einer einzigen SQL-Anfage einen kompletten Teilbaum laden. Oder man kann mit einer Anfrage zählen lassen, wieviele Knoten ein Teilbaum hat. Oder man kann sich den Pfad von der Wurzel zu einem Knoten geben lassen usw.
Intern basiert das Ganze auf einer Pre-Order Anordnung der Baumknoten. SQL-Anfragen laden quasi Teilbereiche aus dieser Pre-Order Anordnung. Aus der geladenen Liste kann der Teilbaum rekonstruiert werden.
Nachteil bei "Nested Sets" ist der Aufwand bei Änderungen. Um ein Element einzufügen oder einen Teilbaum zu löschen, müssen alle in der Pre-Order Reihenfolge nachfolgenen Baumknoten per SQL-Update aktualisiert werden. Das benötigt zwar selbst nur 2 SQL-Anweisungen - 1. nachfolgende Knoten verschieben (Platz schaffen für einen neuen Knoten schaffen oder frei gewordene Lücke schliessen), 2. Knoten einfügen oder löschen - das ist aber dennoch sehr aufwändig.
Eigentlich sind das Formatangaben. Genauso gut könntest du fragen, wie man kursive Zeichen in einem String speichert.
Aber vielleicht gibt es wirklich was dafür in Unicode. Man kann ja in Unicode Zeichen kombinieren, wodurch das resultierende Zeichen anders dargestellt wird.
Vielleicht findest du hier was: http://www.unicode.org/charts/symbols.html
Dort gibt es u.a. den Zeichensatz für "Super and Subscripts", allerdings nur für mathematische Symbole.
du kannst den IE als Klasse importieren. Dann hast du Zugriff auf alle Eigenschaften und Methoden und kannst z.B. auch die Darstellung anpassen. Toolbar, Addressleiste, Statusleiste ein- und ausblenden und solche Sachen.
Einfach in der IDE einen COM-Verweis zum Projekt aus der Bibliothek %windows\system32\shdocvw.dll hinzufügen. Ausserhalb einer IDE funktioniert das mit dem Type-Library Importertool TlbImp.exe.
Das Problem mit den doppelten Instanzen löst sich so von selbst, da du dann ein IE-Objekt hast und dort Visible = true/false, Activate usw. aufrufen kannst.
Deswegen nennt man Klassen auch Referenztypen. Es werden nur Referenzen auf Objekte umhergereicht, keine Kopien.
Wenn du eine Kopie brauchst, kannst du z.B. das ICloneable-Interface implementieren oder du fügst deiner Klasse einen Kopier-Konstruktor hinzu. Ein Konstruktor, der ein Objekt des selben Types entgegennimmt und aus diesem die Werte entnimmt, um ein zweites Objekt zu initialisieren.
Du kannst statt einer Klasse auch eine Struktur verwenden. Das wäre dann ein Wertetyp. Wertetypen werden bei einer Zuweisung kopiert. Bei jeder Zuweisung, also wenn es eine grosse Struktur ist, bisschen darauf achten.
Du hast dir doch nicht etwas Sonys Rootkit eingefangen? Ich könnte mir vorstellen, dass das genau sowas macht. Abspielen von Mp3s verhindern oder deinen USB-Stick vorbereiten, damit, falls du Mp3s kopierst, diese auf anderen Rechnern auch nicht abspielen kannst.
Ich weiss, ne sehr weit hergeholte Vermutung. Aber kann man ja mal mit in Betracht ziehen.
Eine Fassade kann man als eine Art Steuerzentrale für ein System sehen.
Sie verbirgt ein grösseres, nicht einfach handhabbares, aber dennoch erforderliches Klassenmodell. Die Verwendung der Funktionen des Klassenmodell wird erleichtert, aber auch eingeschränkt. Es geht Flexibilität verloren.
Mit Vererbung und Interfaces hat das überhaupt nichts zu tun. Im Gegenteil, eine Fassade ist meistens eine fest implementierte, sehr spezielle Klasse. Ihre Schnittstelle ist eine ganz andere als die der Klassen, die sie verbirgt.
Nach der Liste dort könnte auch bald C++ von PHP überholt werden (Platz 3). Andererseits sind die Ergebnisse wahrscheinlich nicht so aussagekräftig, da die Platzierungen anhand von Suchmaschinentreffern ermittelt werden. Und PHP ist nunmal eine Scriptsprache für Webseiten, während C++ mehr in Offline-Anwendungen anzutreffen ist. Aber naja.
Das hat aber nur einen sichtbaren Effekt, wenn das Bild in der PictureBox nicht die gesamte Fläche ausfüllt. ForeColor bringt in so einem Fall auch nichts, die bezieht sich nur auf die Schriftfarbe.
Bleibt noch, die Farbe direkt im Image zu ändern. Dafür müsstest du dich mit der System.Drawing.Graphics-Klasse und dem System.Drawing.Imaging-Namespace auseinandersetzen.
Hier noch ein Weg kurz angedeutet, wie man in einem Bild eine Farbe durch eine andere ersetzen kann. Ich hoffe das Prinzip wird einigermaßen klar, wenn du es dir in der Msdn-Doku angesehen hast:
Wenn es gültiges Xml ist, würde ich im ersten Schritt die XMP-Elemente als Ganzes auslesen - mit einem XmlReader oder als XmlDocument. Der Text im XMP-Element kann dann mit String.Split oder besser Regex.Split weiter aufgesplittet werden. String.Split macht Probleme, wenn gleiche Trennzeichen aufeinander folgen, z.B. mehrere Leerzeichen.
Split-Regex: @"\s*\r?\n\s*"
Trennt an Zeilenumbrüchen und entfernt gleich führende und nachfolgende Whitespaces.
Du musst die Lade-Komponente, die "das Teil" lädt, Ereignisse feuern lassen und du musst ungefähr wissen, wieviele Ereignisse gefeuert werden.
Diese Informationen braucht man, um eine ProgressBar zu aktualisieren. Wenn man die nicht hat, bleibt nur noch eine Pseudo-Fortschrittsanzeige, die z.B. hin- und herläuft.
.. und häufig nicht nachvollziehbar. Manchmal tritt der Effekt auf, manchmal wieder nicht und im Debugger sowieso immer ganz anders.
Also, wenn irgendwie möglich, sollte man auf Threads verzichten. Allerdings, Application.DoEvents ist kein Ersatz. Dann schon lieber Threads und sehr viel testen, dass sichergestellt ist, dass die Vorgänge immer synchron und vorhersehbar ablaufen. Threads, wenn sie auf die selben Daten zugreifen, kann man sich wie in einem rundenbasierten Strategiespiel vorstellen. Wenn ein Thread aktiv ist, müssen die anderen warten.
Das nur so nebenbei. Hat nichts mit dem "GUI <-> Thread Problem" zu tun. Da muss in jedem Fall mit Control.Invoke / Control.BeginInvoke gearbeitet werden.
Nur der GUI-Thread - der Thread, in dem die Forms instanziiert wurden und in dem die Windows-Botschaften-Warteschlage läuft - nur der darf direkt auf Windows-Controls zugreifen. Ansonsten gibt es Probleme. Ein Relikt aus der alten Windows-Programmierung, die nur einen einzelnen Thread erlaubt hat (Single Thread Apartment). Alle Aktionen mit Windows-Controls müssen per Botschaft über die Botschaften-Warteschlange durchgeführt werden.
In .Net 2.0 wird das mittlerweile zur Laufzeit sichergestellt. Es wird eine Exception geworfen, wenn ein anderer Thread auf die GUI zugreift. In .Net 1.1 gab es da nur nicht nachvollziehbare, merkwürdige Effekte, wenn man sich nicht daran hielt.
Du kannst dir natürlich auch alle Felder einer Klasse geben lassen und gucken, welche ein SkinControlAttribute gesetzt haben. Dann braucht man die Feldnamen nicht.
Ein Szenario wo das vorkommen kann:
- die Methode mit der Schleife kann die Abbruchbedingung nicht selbst initialisieren.
- die Schleife soll mindestens einmal durchlaufen werden.
Konkretes Szenario:
- zwei oder mehr Threads synchronisieren sich per WaitHandle.
- bekommt ein Thread das Signal zum Weiterlaufen, prüft er zunächst eine Bedingung.
- ist diese nicht erfüllt, kehrt er zurück in den Wartezustand.
Würde die Bedingung gleich zu Beginn geprüft, würde der Thread die Warteanweisung immer überspringen und die anderen Threads würden für immer blockieren.
Na fürs Logging kann man sowas auf jeden Fall gebrauchen. Innerhalb einer Transaktion werden werden viele kleine Transaktionen für Log-Ausgaben durchgeführt. Wenn jetzt die grosse Transaktion schiefläuft, bleiben die Log-Einträge trotzdem erhalten. Wie kann man das anders nachbilden?
In Java ist sowas kein Problem. Dort gibt man der Logging-Methode eine Annotation (ein Attribut) mit, dass sie in einer eigenen Transaktion laufen soll. Eine schon laufende Transaktion wird in der Zeit ausgesetzt und im Anschluss normal fortgesetzt. Beide Transaktionen laufen unabhängig von einander.
Ich hab aber keine Ahnung wie das auf Datenbank-Ebene gelöst ist, also welche Befehle an die Datenbank gesendet werden. Das ist das Problem mit Attributen/Annotationen. Man weiss nicht mehr genau was da eigentlich passiert. Auf jeden Fall soll es auch mit dem MS SQL-Server funktionieren.
(?≤Ecu_Name\(S:) ist ein positiver Lookbehind:
- eine Gruppe, die auf "Ecu_Name(S:" matcht, die aber nicht im Ergebnis auftaucht.
[^)]* greift sich alles, was keine "runde Klammer zu" ist.
Die Matches des Regex sind genau die Strings, die du haben möchtest. Also "SAMH164", "KL164" und "KIXAGW164".
private static Regex ecuNameRegex = new Regex(
@"(?≤Ecu_Name\\(S:)[^)]*",
RegexOptions.Compiled);
private List GetEcuNames(string text) {
List ecuNames = new ArrayList();
foreach(Match m in ecuNameRegex.Matches(text)) {
ecuNames.Add(m.Value);
}
return ecuNames;
}