Laden...
P
Pulpapex myCSharp.de - Member
Java-Entwickler Rostock Dabei seit 22.07.2003 939 Beiträge
Benutzerbeschreibung

Forenbeiträge von Pulpapex Ingesamt 939 Beiträge

08.10.2005 - 06:00 Uhr

Events und Indexer sind ganz einfach. Wirst bald merken.

Vielleicht hilft ein Beispiel. Man schreibt Events meistens so:

// Klasse mit Event.

// Geschütze Methode, um das Event auszulösen.
protected void OnChanged()
{
   if(Changed != null)
   {
      Changed(this, EventArgs.Empty);
   }
}

// Event.
public event EventHandler Changed;

Andere Objekte können sich für das Changed-Event registrieren, mit +=, so wie du es schon geschrieben hast.

// Klasse, die das Event abonniert.

private void Init()
{
   obj.Changed += new EventHandler(HandleChanged);
}

private void HandleChanged(object sender, EventArgs e)
{
   Console.WriteLine("Changed-Event ausgelöst");
}

Indexer
Indexers sind eigentlich nur für Collections interessant. Also für Klassen, die Sammlungen von mehreren Objekten darstellen. Braucht man eher selten. Normalerweise reicht es, dass die eigene Klasse eine Collection-Eigenschaft bereitstellt.

Ein Indexer erlaubt einen Array-ähnlichen Zugriff auf Objekte. Hier am Beispiel eines ArrayList-Objektes:

ArrayList list = new ArrayList();
list.Add("abc");
list.Add("def");
string abc = list[0]; // Indexer-Zugriff
string def = list[1]; // Indexer-Zugriff

Das ist der einfachste Fall. Ausser eines Index können auch beliebige andere Datentypen als Parameter definiert werden. Z.B. String, das wäre dann eine Art Hashtable. Mehr als ein Parameter sind auch möglich. Eigentlich ist es nur eine Methode, die mit eckigen Klammern aufgerufen wird.

@herbivore

herbivore
Delegat und Event sind beide Multicast. Der Unterschied ist, das ein Delegat ein Feld ist und ein event ein Feld + Zugriffsmethoden darauf, siehe SerializationException wegen Observer

Man muss zwischen Delegates mit void-Rückgabewert und anderen Rückgabewerten unterscheiden. Nur void-Delegates sind multicastfähig.

Gruss
Pulpapex

28.09.2005 - 23:10 Uhr

Einige tausend Anfragen, 20 Anfragen gleichzeitig.

Das hast du doch schon fast: 20 Threads, jeder sendet in einer Schleife, sagen wir, 500 Anfragen.

Dass die Threads minimal verzögert starten, spielt bei Webzugriffen keine Rolle. Wenn doch, könnte man die Threads direkt nach dem Start an einem WaitHandle blockieren und dann gleichzeitig(er) loslaufen lassen.

Gruss
Pulpapex

28.09.2005 - 22:52 Uhr

hi tomaten,

ich selbst bin der Meinung, dass Java mit Eclipse um Längen besser ist als .Net und VS.Net, mal verschärft ausgedrückt. Aber es interressiert hier wirklich keine Sau.

Wenn du deine Probleme immer mit Delphi vergleichst, werden die wenigsten hier dir weiterhelfen können, da kaum oder veraltete Delphi-Kenntnisse. Wahrscheinlicher ist es, dass das Thema abweicht und über Programmiersprachen oder sonst was geflamt wird. Siehst ja wie die Diskussion hier ausartet. Das ist zwar schade, man sollte schon über den Tellerrand gucken können, aber es läuft fast zwangsläufig so.

Aber als C#-Einsteiger, falls du einer bist, sollte man vorsichtig sein mit Vergleichen mit seiner alten Programmiersprache. Man weiss einfach noch zu wenig. Sowas gab es hier schon ab und zu, z.B. C++ Profis, die nicht damit klar kommen, dass es nicht mehr genauso geht wie bisher.

Gruss
Pulpapex

25.09.2005 - 02:05 Uhr

@tb, in .Net kommt es zu ner NullReferenceException.
... alter Java-Programmierer. 😉

@kocum, das bisher Geschriebene zusammengefasst:

Person[] personen = new Person[3]; // Array instanziieren.
personen[2] = new Person(); // Person 2 instanziieren.
personen[2].Name = Console.ReadLine(); // Name setzen.
24.09.2005 - 05:34 Uhr

Gibt es nicht, könntest du aber leicht selbst schreiben.

Rekursiv durch die Controls-Eigenschaften aller Container, ausgehend vom MainForm, iterieren und die Name-Eigenschaft jedes Controls mit "btnDrueckMich" vergleichen.

In der Art und Weise:

// MainForm

public Control FindControl(string name) {
   return FindControlRecursive(name, this.Controls);
}

private Control FindControlRecursive(string name, ControlCollection controls) {
   // Impl.
}

Der Code oben kann das MainForm nicht finden. Vorschlag 2:

// MainForm

public Control FindControl(string name) {
   return FindControlRecursive(name, this);
}

private Control FindControlRecursive(string name, Control parentControl) {
   // Impl.
}

Gruss
Pulpapex

24.09.2005 - 05:15 Uhr

Wie äussert sich das Einfrieren? Keine Reaktion auf Tastendrücke oder nur träge?

die Anwendung wird mit Threads ja nicht schneller, eher langsamer mit den heutigen Single-Core Prozessoren. Das sollte aber nicht viel ausmachen. Trotzdem, falls du gehofft hast, dass durch Threads die Anzeige schneller aktualisieren wird, das wird nichts werden.

Ansonsten sieht der Code eigentlich ganz ok aus. BeginInvoke verhindert einen Blockieren des Threads. Die Anzeige-Aktualisierung wird in die Windows-Botschaften-Warteschlange gestellt und irgendwann ausgeführt. Der BeginInvoke-Aufruf kehrt sofort zurück, der Thread wartet nicht bis die Anzeige aktualisiert wurde.

Probier es nochmal mit Invoke, statt BeginInvoke. Dann wird der Thread zwar blockiert, aber die Anzeige aktualisiert vielleicht schneller.

Gruss
Pulpapex

23.09.2005 - 13:12 Uhr

Mit dem ComImport-Attribut kann man es machen.

Hier hatte ich ein Beispiel gepostet:
ActiveX ohne Verweis

Einfacher ist es aber in der IDE oder mit TlbImp.exe eine Wrapper-DLL generieren zu lassen, so wie svenson es vorschlägt und wie du es auch schon gemacht hast -> Referenz aus COM einbinden. Es wird der gleiche Code generiert, den man sonst per Hand schreiben müsste.

Gruss
Pulpapex

23.09.2005 - 12:47 Uhr

Das wird nicht besser gehen. Die Anzahl der Textzeilen entspricht der Anzahl der NewLine-Zeichen (+1). Und um die NewLines zu zählen, muss der komplette Text gelesen und durchsucht werden.

Gruss
Pulpapex

22.09.2005 - 23:41 Uhr

Umlaute sind in XML und HTML nicht erlaubt, die müssen durch Entities ersetzt werden. HTML definiert z.B. ä für ä oder ü für ü usw. In XML verwendet man Unicode-Entities, z.B. & #228; für ä.

http://www.w3schools.com/tags/ref_entities.asp

"Löhnert" sieht mir nach UTF8 aus. Dass du in der Html-Datei charset=iso-8859-1 angibst, bedeutet ja nicht zwangsläufig, dass sie auch so kodiert ist. Vielleicht bringt es was stattdessen da UTF-8 einzutragen, weiss ich aber nicht.

Gruss
Pulpapex

21.09.2005 - 17:03 Uhr

Das geht mit System.Windows.Forms.ControlPaint.DrawSelectionFrame. Die Methode zeichnet per Graphics-Objekt auf ein Windows-Control (oder einen anderen Graphics-Context).

Msdn: ControlPaint.DrawSelectionFrame

Gruss
Pulpapex

// Verschoben nach Windows-Forms

20.09.2005 - 16:11 Uhr

Statt mit \s, muss mit \s+ gesplittet werden. Das sollte es gewesen sein.

20.09.2005 - 14:01 Uhr

Du kannst statt des Forms-Timers einen System.Threading.Timer verwenden. Der TimerCallback-Delegat wird ohne Zutun in einem eigenen Thread ausgeführt.

20.09.2005 - 12:14 Uhr

Nein,

ich habe den Aufbau oben angedeutet, kein B-Baum. Laut Wikipedia nennt sich das Trie-Baum.

20.09.2005 - 10:41 Uhr

Du bist jetzt genau über diese Invoke-Geschichte gestolpert. Im Thread ausgeführter Code darf nicht direkt auf Windows-Controls zugreifen, sondern muss dafür Invoke verwenden.

private void tima_Tick(object sender, EventArgs e)
{
   // Läuft nicht im UI-Thread, darf so nicht auf label1 zugreifen.
   label1.Text = DateTime.Now.ToLongTimeString();
}

Für dein Beispiel mit dem System.Windows.Forms.Timer ist eigentlich kein zweiter Thread erforderlich (aber du willst ja gerade Threads ausprobieren).

Such mal im Forum nach Control.Invoke oder ISynchronizeInvoke.

_// Edit: _
Zu der Sache, warum keine Exceptions geworfen werden. Exceptions in Threads erzeugen keinen StackTrace, es wird nur der Thread beendet. Deshalb den Code in Threads immer komplett in try-catch-Blöcke einschliessen.

20.09.2005 - 09:00 Uhr

Ich habe eine StringSearchDictionary-Klasse geschrieben. Die erlaubt die Suche mit Wildcards (*, +, ?, ., {m,n}). Man kann auch eine Liste mit Zeichen angeben, auf die die Suche eingechränkt werden soll, allerdings nicht so wie du es brauchst.

Beispiel:

StringSearchDictionary dict = new StringSearchDictionary(stringColl);

IList resultList = dict["ab*nen"];
dict.Remove("ab*nen+");

Intern basiert das Ganze auf einer Baumstruktur. Jedem Baumknoten ist ein Zeichen zugeordnet. Ein String als Schlüssel definiert mit seinen Zeichen einen Pfad in den Baum. Im letzten Knoten des Pfades ist der Wert zum Schlüssel abgelegt. Diese Art von Baum eignet sich besonders gut für Wildcard-Suchen. Sie wird häufig in elektronischen Wörterbüchern eingesetzt.

Wenn dir die Klasse was nützt, kann ich sie heute abend mal online stellen. Sie ist auf jeden Fall sehr schnell. Suchen in 20.000 Begriffen erfolgt ohne spürbare Zeitverzögerung, selbst wenn die Ergebnisliste gross ist.

Gruss
Pulpapex

20.09.2005 - 08:32 Uhr

Original von herbivore
Wobei ich es klarer finde, wenn man Control.Invoke sagt. Ist aber Geschmackssache.

Sehe ich auch so. Es gibt nur eine Klasse, die ISynchronizeInvoke implementiert, und zwar System.Windows.Forms.Control.

Das Interface existiert nur, damit Assemblies nicht die System.Windows.Forms.dll referenzieren müssen, um sie unabhängig von Windows Forms zu halten. Direkt im Code verwenden tut man es aber eher selten, finde ich zumindest. Man hantiert eher mit Controls und deren Members.

19.09.2005 - 16:39 Uhr

Hallo m4niac,

du kannst im TemplateChose-EventHandler das geklickte MenuItem ermitteln:

private void TemplateChose(object sender, EventArgs e) {

   MenuItem itemClicked = (MenuItem)sender;
   int indexClicked = itemClicked.Index;
   string itemText = itemClicked.Text;
}

Gruss
Pulpapex

16.09.2005 - 12:09 Uhr

Dann gibt es noch Visual Paradigm. Gibt es für viele Sprachen und IDEs. Ich hatte mal die Eclipse-Integration ausprobiert. War sehr angenehm und einfach damit zu arbeiten. Nur leider ist es ziemlich teuer und die kostenlose Version ist wie immer stark eingeschränkt.

16.09.2005 - 10:19 Uhr

Form.Load wird ausgelöst, kurz bevor ein Formular angezeigt wird. Falls du das meinst.

// Verschoben nach Windows-Forms

16.09.2005 - 08:46 Uhr

Die andere Frage ging eher in die Richtung, ob es natives C++ ist oder managed C++, das schon genau wie C# in die IL-Zwischensprache übersetzt wird. Im zweiten Fall hättest du mit einem Decompiler nach C# zurückübersetzen können. Nur für den Einstieg, wahrscheinlich wäre der Code voll von unsafe-Blöcken wo mit Zeigern hantiert wird.

Aber da es um eine COM-Komponente geht, wird es wahrscheinlich natives C++ sein. Das wirst du von Hand übersetzen müssen. Und wahrscheinlich wirst du mit COM-Interop arbeiten müssen. Besonders am Anfang ist das nicht gerade trivial.

Gruss
Pulpapex

16.09.2005 - 08:34 Uhr
        
        PrintDocument doc = new Printing.PrintDocument();

[STAThread]
static void Main(string[] args)
{
        doc.PrintPage += new PrintPageEventHandler(printPage);
}

doc ist eine Instanz-Variable. In der statischen Main-Methode ist diese Variable nicht sichtbar. Der Compiler versucht jetzt doc als Klasse zu interpretieren, findet sie aber nicht.

Wenn der Code so bleiben soll, musst du die doc-Mitgliedsvariable static deklarieren.

Gruss
Pulpapex

15.09.2005 - 22:06 Uhr

Ich hab mal in den Link von maxE reingeschaut.

Objekt- und Collection-Initializers sind eine gute Idee, finde ich. Man kann dann alle (?) Typen schon bei der Deklaration/Instanziierung vollständig initialisieren. So wie man es heute von Arrays her kennt.

List<string> stringList = new List<string> {"abc", "def", "ghi"};
Person p = new Person {Name="Gonzo", Age=28};

Der Sinn hinter impliziter Typisierung hat sich mir auf die Schnelle nicht erschlossen.

var i = 5; // int i
var s = "abc"; // string s

Was soll es bringen, den Typ nicht mit anzugeben, was wird dadurch vereinfacht? Ich seh's schon kommen, in C# 4.0 gibt es den Variant-Typ.

14.09.2005 - 13:00 Uhr

Na dann funktioniert doch alles. Musst ihn nur noch dazu bringen, dass er auf die Position springt, die du haben willst.

14.09.2005 - 12:54 Uhr

Das ist in Java nicht so einfach wie in .Net.

Stichwort "JNI". Man muss sich mit dem javah-Tool eine Header-Datei (*.h) für eine class-Datei mit native-Methoden generieren lassen und dazu eine c-Datei schreiben, die die eigentlich gewünschte Funktion aufruft (EnumServicesStatusEx).

Java Native Interface - Tutorial

Gruss
Pulpapex

14.09.2005 - 12:38 Uhr

Was klappte bei dir denn net so ganz mit

fs.Seek(SeekOrigin.Begin, position);

FileStream unterstützt Seek. Eigentlich sollte es so funktionieren.

13.09.2005 - 20:35 Uhr

In der Windows-Codepage 1252 gibt es keine Zeichen für Rahmen mehr. _:::

Versuch' es mal mit _:::

Gruss
Pulpapex

12.09.2005 - 22:16 Uhr

Man kann es auch von der anderen Seite betrachten.

Control.Invoke ist ein Workaround für eine aus der Win-Api geerbte Unzulänglichkeit von Windows-Forms, nicht mit mehreren Threads umgehen zu können. Warum diese technische Eigenart veröffentlichen und dadurch das Interface versauen?

Es wird quasi unbenutzbar. Und es wird fehleranfälliger, da Members öffentlich gemacht werden, die nicht verwendet werden dürfen - jedenfalls nicht direkt.

Hier ein Beispiel wie ich das meine:

public interface IFileProcessorView {
   public string CurrentAction( get; set; );   // Nur über UIThread aufrufen.
   public string CurrentFile( get; set; );     // Nur über UIThread aufrufen.
   public double OverallProgress( get; set; ); // Nur über UIThread aufrufen.
   public double FileProgress( get; set; );    // Nur über UIThread aufrufen.
   public ISynchronizeInvoke UIThread { get; }
}

// Im Thread ausgeführte Methode.
private void ThreadMethod() {

   IFileProcessorView view = this.fileProcessorView;

   // Verboten!
   view.CurrentAction = "Deleting File ...";


   // Stattdessen folgender Code ...

   // Parameter für BeginInvoke vorbereiten.
   SetCurrentActionDelegate setCurrentAction = 
      new SetCurrentActionDelegate(SetCurrentAction);
   string[] action = new string[] {"Deleting File ..."};

   // BeginInvoke: im UIThread ausführen.
   view.UIThread.BeginInvoke(setCurrentAction, action);
}

// Für den Delegaten notwendige Hilfsmethode.
private void SetCurrentAction(string action) {
   IFileProcessorView view = this.fileProcessorView;
   view.CurrentAction = action;
}

// Delegate für Invoke.
private delegate void SetCurrentActionDelegate(string action);

Das wiederholt sich an allen Stellen wo auf das Interface zugegriffen wird.

Versteckt man den Code in der Implementierung, braucht man sich nicht mehr darum zu kümmern und kann die Interface-Members wieder direkt verwenden. Nur die Implementierung soll ja wissen, dass im Hintergrund Windows-Controls aktualisiert werden.

10.09.2005 - 03:50 Uhr

Geht es nicht noch einfacher?

Klasse A ruft aus einem "Nicht-GUI"-Thread Methoden des Interfaces auf. Das Interface soll frei von Forms und anderem Schnickschnack bleiben. Die konkrete Implementierung des Interfaces aber, die dann aufgerufen wird, aktualisiert Controls wie du gesagt hast. D.h. sie hält Referenzen auf die Controls. Dann kann doch sie Control.Invoke zum Aktualisieren benutzen. Wozu das öffentliche Interface erweitern?

Gruss
Pulpapex

06.09.2005 - 20:24 Uhr

In Threads ausgeführten Code würde ich immer komplett in einen try/catch-Block einschliessen. Ansonsten bekommt man nicht mit, wenn eine Exception auftritt. Der Thread wird nur still und leise beendet.

Gruss
Pulpapex

06.09.2005 - 08:24 Uhr

Ist natürlich sehr einfach, der Algorithmus und physikalisch wahrscheinlich nicht besonders korrekt. Aber es sieht zumindest realistisch aus.

Gegenstände werden von Wellen umspült. Ein bewegter Körper zieht einen Wellenkeil hinter sich her. Ein Tropfen breitet sich kreisförmig mit mehreren Wellenbergen aus. Alles so wie man es kennt.

Was z.B. nicht modelliert ist, ist das Verhalten bei unterschiedlichen Wassertiefen. Dass sich Wellen im flachen Gewässer auftürmen usw. Überschlagende Brecher und Brandung natürlich auch nicht. Und wirklich bewegtes Wasser, wie Strudel und Strömungen auch nicht. Nur Wellen.

05.09.2005 - 22:18 Uhr

Der Wassereffekt ist ein ganz einfacher Algorithmus. Fakultäten und große Zahlen braucht man dafür nicht. Man braucht nicht mal Fließkommazahlen.

Diese Seite hier erklärt den Algorithmus im Detail:
The Water Effect Explained

Ich hatte das mal mit der Seite als Grundlage in Java nachprogrammiert, zum Testen der Geschwindigkeit von SWT (GUI von Ecplise). Läuft flüssig und sieht realistisch aus.

Hier noch eine Seite mit weiteren Implementierungen, zu finden im Abschnitt "Physical Models/Water":
efg's Simulation and Modelling Page

Gruss
Pulpapex

02.09.2005 - 20:29 Uhr

Hi,

byte []buffer = new byte[36769];

Passt das komplette Bild des Desktops überhaupt in 35 kByte?

int iBytes = clientsocket.Receive(buffer);

Der Aufruf schreibt nur so viele Bytes in den Buffer, wie in iBytes zurückgegeben wird. Receive muss mehrfach aufgerufen werden, um das Bild komplett zu empfangen. Der Inhalt des Buffers muss dafür natürlich jedes Mal gesichert werden. Oder man verwendet die Receive-Überladung, wo man zusätzlich ein Offset in den Buffer angeben kann.

Wenn nichts dagegen spricht, schau dir die TcpClient-Klasse mal genauer an. Das ist quasi eine Highlevel-API für Sockets.

Beispiel:

Stream stream = tcpClient.GetStream();
Image im = Image.FromStream(stream);

Gruss
Pulpapex

01.09.2005 - 14:29 Uhr

Na der GameStateManager schaltet die States um. Also ist es wahrscheinlich auch seine Aufgabe, die State-Controls in der MainForm auszutauschen. Dafür benötigt er eine GameStateManager.MainForm-Eigenschaft, in der die Arch-Form von aussen gesetzt werden kann.

Gruss
Pulpapex

01.09.2005 - 14:14 Uhr

Hi nitronic,

Highlighting für Textbereiche, also für Copy & Paste, kommt im zweiten Teil. Das steht ganz unten im Artikel.

Im Moment wird nur in der Umgebung des Cursors hervorgehoben. Deshalb wundert es mich, dass es bei viel Text flimmern soll. Sollte eigentlich keine Rolle spielen. Ich werde das heute abend mal testen.

@Fabian - den zweiten Teil werde ich die nächsten Tage in Angriff nehmen. Mal schauen.

01.09.2005 - 12:17 Uhr

Es fehlt der Code, der das TitleScreenControl zum Arch-Form hinzufügt.



// Control des letzten States entfernen.
archForm.Controls.Clear();

// Control für den TitleScreen-State hinzufügen.
TitleScreenControl titleScreen = new TitleScreenControl();
archForm.Controls.Add(titleScreen);

Gruss
Pulpapex

29.08.2005 - 15:39 Uhr

Ich bin auf folgenden Regex gekommen (quasi der selbe wie der von herbivore):

@"([\s:=]+)\s*[:=]?\s*(.*)$"

Aufbau:

  • Name-Gruppe "([^\s:=]+)": alles bis zum ersten "\s", ":" oder "=" (exklusive).
  • Trennzeichen "\s*[:=]?\s*": "\s", ":" oder "=". "\s" auch mehrfach möglich.
  • Wert-Gruppe "(.*)": egal was, bis Zeilenende.

Der Regex matcht aber ausnahmslos alles, z.B. auch:

  • Name == Wert
  • #das ist ein Kommentar.

Die Textdatei darf also nur gültige Name-Werte-Paare enthalten. Das Problem ist, dass "\s" als Trennzeichen zwischen Name und Wert erlaubt ist und dass Trennzeichen auch im Wert vorkommen dürfen. Der exakt matchende Regex dürfte komplizierter und stark in die Länge gezogen ausfallen.

Gruss
Pulpapex

27.08.2005 - 04:17 Uhr

Ich glaube Threads machen dir an der Stelle mehr Probleme, als dass sie helfen. In einer Simulation kommt es auf Nachvollziehbarkeit an, Threads aber arbeiten eher nichtdeterministisch. Es ist überhaupt nicht einfach, Threads exakt zu synchronisieren, ist schon bei zwei Threads schwierig. Am Ende bist du nur damit beschäftigt das Ablaufverhalten der einzelnen Threads in den Griff zu bekommen, statt dich um das eigentliche Simulationsproblem zu kümmern.

Kurzum, Threads verkomplizieren das Problem nur, ich würde sie weglassen.

Gruss
Pulpapex

26.08.2005 - 23:41 Uhr

Rein informativ:

Tiobe erstellt schon seit ein paar Jahren einen Index über die Grösse der Community einer Programmiersprache.
http://www.tiobe.com/tpci.htm

Was die .Net-Sprachen angeht, liegt C# da klar vor VB.Net. C# liegt auf Platz 7, VB.Net auf Platz 15.

Auf der anderen Seite gibt es viel mehr VB-Programmierer/Projekte (Platz 6) als auf C#-Seite. Wenn man den Prozentangaben trauen kann, mehr als doppelt so viele.

Und gegen Java, C und C++ (Plätze 1, 2 und 3) ist C# quasi 'ne Außenseiter-Sprache. Sagen wir mal noch (obwohl der Abstand gewaltig ist 😉 ).

26.08.2005 - 19:44 Uhr

Arrays in VB sind nicht wirklich dynamisch, oder? Um die Grösse zu ändern, muss man explizit redimensionieren. Man muss eigentlich vorher wissen wie gross das Array werden soll.

ILists und List<T> passen ihre Grösse wirklich dynamisch an und sind einfacher handhabbar. Dafür sind sie im Zugriff wahrscheinlich langsamer.

Ansonsten, VB-Programmierer können sich ja ne ReDim-Funktion nachprogrammieren:

// Main.
static void Main() {

	byte[] bytes = { 0, 1, 2, 3, 4 };

	// Redimensionieren mit Länge 3, Elemente beibehalten.
	byte[] redim = (byte[]) ReDim((Array)bytes, 3, true);
}

// ReDim-Funktion.
private static Array ReDim(Array array, int length, bool preserve) {

	Type elemType = array.GetType().GetElementType();
	Array redimArray = Array.CreateInstance(elemType, length);

	if(preserve) {
		int len = array.Length < length ? array.Length : length;
		Array.Copy(array, redimArray, len);
	}

	return redimArray;
}

Was anderes macht die originale ReDim-Anweisung auch nicht (nehm' ich mal an).

Gruss
Pulpapex

24.08.2005 - 22:29 Uhr

Ich denke es geht darum, dass die Anwendung auf dem Server an die Referenz eines registrierten Service-Objekts kommen soll. Lokal sozusagen.

Das geht aber in zweierlei Hinsicht nicht. Zum einen ist es ein SingleCall-Service (wer J2EE kennt, entspricht einen "Stateless Session Bean"). Weil der SingleCall-Service keinen Zustand speichert, macht es auch keinen Sinn sich ein bestimmtes Objekt zu holen. Sie sind alle gleich und können wiederverwendet werden. Es gibt einen Pool, in dem "gebrauchte" SingleCall-Objekte gecached werden.

Und zweitens, selbst bei einem Singleton-Service bekommt die Server-Anwendung keinen "lokalen" Zugriff auf das Objekt. Sie muss sich auch die "Proxy"-Referenz holen, genauso wie es der Client tut. (Es wird ja die Klasse als "WellKnown" registriert und nicht ein spezielles Objekt, das man noch lokal referenziert haben könnte.)

Registrierte Services können also nur remote aufgerufen werden. Befinden sich Client und Service auf dem selben Rechner, können die Kommunikationswege optimiert werden. Ich glaube statt TCP/IP kommt dann COM+ zum Einsatz, bin mir aber nicht sicher.

Gruss
Pulpapex

23.08.2005 - 23:32 Uhr

Dann ist es Punkt 2.

Exceptions in Threads gehen wie gesagt still und leise unter. Der Thread wird ohne Meldung abgebrochen.

In der IDE bekommt man es durch dieses "Exception-Breakpoint"-Feature mit. Der Debugger stoppt dort, wo die Exception auftritt.

Damit man Exceptions auch in Threads mitbekommt, würde ich den kompletten Code immer in einen try-catch-Block einschliessen.

try {
   // Code.
} catch(Exception ex) {
   Console.WriteLine(ex);
}
23.08.2005 - 23:17 Uhr

Hi liam,

nur zwei Vorschläge/Ideen:

  • Hast du mal geguckt was QueueUserWorkItem zurückgibt? In der Doku steht, dass false zurückgegeben wird, wenn der WaitCallback nicht in die Warteschlange gestellt werden konnte (Es steht nur leider nicht dabei, wann das der Fall sein kann).

  • Es steht zwar kaum was in den Methoden drin, aber schreibe trotzdem mal try-catch-Blöcke drum rum. Bei Exceptions, die in einem Thread auftreten, gibt es keinen Stacktrace auf der Konsole oder sonst eine Meldung. Muss man selbst für sorgen.

Gruss
Pulpapex

23.08.2005 - 22:57 Uhr

Das Array mit den Indizes fehlt noch oder? Es gibt eine System.Array.Sort-Überladung, die sortiert gleichzeitig zwei Arrays. Das zweite Array wird analog zum ersten sortiert.

So sollte es gehen, habs aber nicht ausprobiert:

// Array mit int-Werten.
int[] values = //;

// Kopie erstellen, das Original-Array soll nicht sortiert werden.
int[] valuesCopy = new int[values.Length];
values.CopyTo(valuesCopy, valuesCopy.Length);

// Array mit den zu sortierenden Indizes erstellen.
int[] indices = new int[values.Length]
for(int i = 0; i < indices.Length; i++) {
   indices[i] = i;
}

// Values-Kopie sortieren, Indizes werden analog sortiert.
Array.Sort(valuesCopy, indices);

Gruss
Pulpapex

20.08.2005 - 14:34 Uhr

es muss heissen:

private string path;

Auf die Gross-/Kleinschreibung achten.

Ich hatte noch vergessen, die path-Variable private zu deklarieren. Habe ich jetzt verbessert.

20.08.2005 - 14:20 Uhr

Ein gutes Beispiel, warum man keine öffentlichen, schreibbaren Felder definieren soll. Eine Klasse mit so einem Feld bekommt nicht mit, wenn der Wert geändert wird.

public class Test {

  private string path;

  public Test() {
     Path = Application.StartupPath;
  }

  // Path-Eigenschaft.
  public string Path {
     get { return this.path; }
     set {
        this.path = value;
        BuildPath(this.path);
     }
  }
}

20.08.2005 - 10:13 Uhr

Ich nicht,

so wie ich es verstanden habe, geht es in erster Linie noch gar nicht ums Speichern in einer Datenbank oder einer Datei. Es geht um die Datenhaltung im Speicher damit man damit arbeiten kann.

Und da würde ich die Daten nicht in einem XmlDokument halten, nur weil sie aus einer Xml-Datei geladen wurden oder in einem DataSet, weil sie aus einer Datenbank kommen. In einer OO-Anwendung werden die Daten normalerweise in einem Objektmodell (Klassendesign des abzubildenen Teils der realen Welt) gehalten.

Ich würde es genauso lassen wie es ist. Pharmacy ist eine Klasse/Struct des Objektmodells, sie definiert die benötigten Daten und die anwendbaren Operationen. Eine zweite Klasse ist der PharmacyManager, der für das Anlegen, Laden, Speichern, Löschen usw. von Pharmacy-Objekten zuständig ist. Wie und was nun genau gespeichert wird, bleibt seine Sache. Die Anwendung sieht nur Pharmacy-Objekte.

Gruss
Pulpapex

20.08.2005 - 01:40 Uhr

Wie wäre es mit etwas Code? Du sprichst in Rätseln.
Es geht wohl irgendwie um Konstruktoren? Auf den Titel des Beitrags wird auch nicht weiter eingegangen.

Titel: "Member-Variable des Clients vom Server setzen lassen" (sinngemäß)
Client ruft auf, Server reagiert:

class Client {

   Client () {
      // server =
      server.SetClientVar(this);
   }

   public string Var { get; set; }
}

class Server {
   public void SetClientVar(Client client) {
      client.Var = "C:\\\\";
   }
}

Mehr ist bei der Beschreibung nicht drin ...

19.08.2005 - 23:14 Uhr

herbivore

ikaros
Ist der grössere Aufwand des Designs in einem solchen Fall mehr hinderlich?
Auch wenn du es nicht glauben oder hören willst: Meiner Erfahrung nach ist größere Aufwand beim Designs in einem solchen Fall nützlich.

Es gibt auch den umgekehrten Ansatz - Extreme Programming.* schlichtes Design.

  • kein Code auf Vorrat / kein Design für die Zukunft / kein mächtiges Framework.
  • Es wird nur umgesetzt was gefordert ist, mit dem minimal möglichen Code.
  • Wenn die Anwendung schon mehr kann, wird zurückgebaut.
  • Weiterentwicklung in kleinen Schritten. Refaktorierung bestehenden Codes. Tägliche Integration, Nightly Builds. Es muss jederzeit eine aktuelle, lauffähige Version verfügbar sein.
  • Der Stand wird in kurzen Zyklen beim Kunden vorgestellt. Es wird entschieden wie es weitergeht und was als nächstes angegangen werden soll. Der Kunde ist immer auf dem laufenden. Es gibt keine Überraschungen durch Missverständnisse. Die Software kann in Teilen schon vor der entgültigen Fertigstellung eingesetzt werden.

Es gibt noch ein paar mehr Punkte, die ich hier aber nicht alle aufzählen will. Es sind viele kleine, einfache Regeln, geboren aus der Erkenntnis heraus, dass zu weite Vorausplanung in vielen Fällen einfach Zeitverschwendung ist. Vieles der Vorplanung/Entwicklung muss wieder umgeworfen werden - neue Erkenntnisse/Einblicke während des Programmierens, Änderungs-/Erweiterungswünsche vom Kunden (der Kunde weiss auch nicht von Anfang an was er haben möchte) usw. Oder noch schlimmer, der Code wird starr und unflexibel und unnötig kompliziert durch ein an der Praxis vorbei designtes Framework.

Hier eine gute Seite zu XP: http://www.frankwestphal.de/ExtremeProgramming.html

Gruss
Pulpapex

19.08.2005 - 12:44 Uhr

Das kann ich mir vorstellen.

Die lokale Variable wird meiner Meinung nach nicht vor Beendigung von Main collected. Wenn das Hauptfenster beendet wird, kehrt die Ausführung nochmal in die Main-Methode zurück. Also ist die lokale Variable immer noch erreichbar. Der GC guckt garantiert nicht in der Ausführung nach vorne, ob die Variable irgendwo nochmal verwendet wird oder nicht. Es werden nur die Referenzen gezählt, oder etwa nicht??

Gruss
Pulpapex

17.08.2005 - 23:12 Uhr

Zum Abhängen von Events benötigt man nicht die originale EventHandler-Instanz.

So geht es auch:

Changed += new EventHandler(HandleChanged);
Changed -= new EventHandler(HandleChanged);

In C# 2.0 reicht sogar:

Changed += HandleChanged;
Changed -= HandleChanged;

Gruss
Pulpapex