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

26.02.2005 - 18:37 Uhr

Sieht halt nicht genauso aus,
aber Struktur und Inhalt weisen doch viele Parallelen auf.

System Namespace
Package java.lang

Was anderes außer die MSDN-Hilfe gibt es auch nicht. Du könntest höchstens versuchen die API-Doku mit NDoc neu zu generieren. NDoc unterstützt neben dem in .Net üblichen MSDN-Format auch das Javadoc-Format.

http://ndoc.sourceforge.net/

Gruss
Pulpapex

26.02.2005 - 17:07 Uhr

Ich habs ausprobiert, funktioniert tadellos.

Zwei Klassen Form1, Form2. Im form1.Load-Ereignis wird form2.ShowDialog(this) aufgerufen. Form2 hat einen Button, im Click-Ereignis wird die form1.Text-Eigenschaft geändert und mit Close die Form geschossen.

Wenn man das Programm startet, erscheint zuert Form2. Klickt man auf den Button, wird Form2 geschlossen und es erscheint Form1 mit geändertem Titel.

Es sollte also funktionieren. Das Problem muss woanders liegen.

Gruss
Pulpapex

26.02.2005 - 15:31 Uhr

Hi Quallo,

man kann ein Bitmap mit Save in einen Stream schreiben. Z.B. in einen MemoryStream. Statt des Bitmaps wird dann das byte-Array aus dem MemoryStream serialisiert.

Bitmap bitmap = //..;
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, ImageFormat.MemoryBmp);
byte[] bitmapBytes = stream.ToArray();

Die Bitmap-Rekonstruktion ist analog: MemoryStream aus byte-Array instanziieren, Bitmap aus MemoryStream instanziieren.

byte[] bitmapBytes = //..;
MemoryStream stream = new MemoryStream(bitmapBytes);
Bitmap bitmap = new Bitmap(stream)

Gruss
Pulpapex

26.02.2005 - 04:21 Uhr

Habe ich tatsächlich schon gewusst.

Aber die Vermutung, dass es sowas geben müsste ist wirklich 'ne Leistung. Mir ist noch nichtmal ein Anwendungsfall in den Sinn gekommen obwohl ich das schon lange kenne. Caches halt, aber das steht in der Doku.

25.02.2005 - 23:50 Uhr

Schau dir mal System.WeakReference an. Ein Objekt in einer WeakReference kann trotzdem vom GC entfernt werden. Unter Java gibt es zusätzlich die WeakHashMap-Klasse. Die wäre genau das was du sucht. In .Net muss man so eine HashMap mit WeakReferences nachbauen.

Gruss
Pulpapex

25.02.2005 - 19:25 Uhr

Warum wird denn noch aus der Datei gelesen, wo doch beim Klick auf den Button gespeichert werden soll?

25.02.2005 - 18:10 Uhr

Nochmal auf den Punkt gebracht,

ein Interface ist die öffentliche Schnittstelle, das von anderen Klassen gesehen und verwendet wird. Dagegen geht es beim Ableiten ums Wiederverwenden einer internen Implementierung. Einmal geht es um die Sicht von außen und einmal um Interna.

Eine Klasse bietet natürlich auch eine öffentliche Schnittstelle. Benutzt man allerdings diese, hat man sich auch auf die Implementierung festgelegt. Das Konzept des Interface-Typs trennt die Schnittstelle von der Implementierung. Wird gegen ein Interface-Typ programmiert, wird die Implementierung austauschbar - siehe das Beispiel dicke Klasse/kleiner Proxy.

Durch Interfaces können verschiedene Klassen gleiche Funktionalitäten anbieten. Sie können dadurch von anderen Klassen auf die selbe Weise verwendet werden. Beispiele für Funktionalitäten sind das Sortieren mit ArrayList.Sort (IComparable) oder das Iterieren in einer foreach-Schleife (IEnumerable).

Gruss
Pulpapex

25.02.2005 - 15:03 Uhr

Ein Interface, ist wie der Name schon sagt, eine Schnittstelle. Es wird von der Implementierung abstrahiert. Das ist es, mehr nicht. Im Gegensatz dazu ist das Erben von einer Basisklasse gerade das Weitergeben vorhandener Implementation.

Stell dir eine gigantisch grosse Klasse vor, 10 Mb Code, 1 Gb Arbeitsspeicherverbrauch und 1 Tb lokale Daten. Eine Anwendung auf einem PDA könnte diese Klasse nicht instanziieren, geschweige denn verwenden.

Hat sie jedoch ein Interface, könnte man einen Proxy programmieren, der nur die Kommunikation mit der dicken Klasse übernimmt. Die Implementierung des Proxies ist eine völlig andere als die der dicken Klasse. Sie ist so verschieden, dass es keine gemeinsame Basisklasse gibt (bis auf Object). Nach außen stellt sich der Proxy aber wie die dicke Klasse dar ... weil beide das selbe Interface implementieren.

Gruss
Pulpapex

25.02.2005 - 09:53 Uhr

Unter Windows muss man dem csc auch die verwendeten Bibliotheken mitteilen. Das hat nichts mit der Installation zu tun.

Versuch es mal so. Ich hab ein bisschen im Netz gesucht, gut möglich, dass die Mono-Assemblies genauso heissen wie die von .Net:

mcs --reference=System.Windows.Forms.dll abc.cs

# alternativ mal so versuchen
mcs -r System.Windows.Forms.dll abc.cs

Wenn sich die Fehlermeldung ändert, ist das schon mal ein Fortschritt.

Auf CodeProject gibt es einen sehr ausführlichen Artikel zu Mono:
Introduction to Mono - Your first Mono app

Da wird auch die ganze Installation nochmal erklärt. Ist vom 25. Jan 2005.

Gruss
Pulpapex

25.02.2005 - 00:10 Uhr

Hi schock,

gut, dass du die Fehlermeldung nochmal vollständig gepostet hast:
"The type or namespace name 'Windows' could not be found in namespace 'System'"

Das hier war total sinnentstellt:
"The type ... Windows could not be found ... in System."

Die Meldung bekommt man, wenn eine benötigte Bibliothek nicht referenziert ist. Also die Bibliothek mit der Mono-Implementierung von System.Windows.Forms.

Auf www.mono-project.com steht, dass für WinForms die Bibliotheken libgdiplus und Cairo benötigt werden. Kann aber gut sein, dass da noch andere Dateien angegeben werden müssen.

Referenzieren geht so:

msc --reference=lib1;lib2 abc.cs

Gruss
Pulpapex

24.02.2005 - 16:20 Uhr

Entweder man arbeitet mit der RichTextBox-API, wie Herbivore vorschlägt - Farbe ändern mit SelectionColor, oder man fügt Formatierungscodes direkt im RTF-Dokument ein.

Siehe: Javadatei in rtf wandeln?

Gruss
Pulpapex

24.02.2005 - 12:01 Uhr

Dispose ist explizit nur für das Interface implementiert. Dadurch ist die Methode in der StreamReader-Klasse nicht sichtbar, StreamReader muss erst ins Interface gecastet werden.

// Das geht nicht
StreamReader sr;
sr.Dispose();

// Das geht.
IDisposable disposable = (IDisposable)sr;
disposeable.Dispose();

Interface-explizit sieht so aus:

// Normal
public void Dispose() {}

// Interface-explizit
void IDisposable.Dispose() {}

MSDN: TextReader.IDisposable.Dispose

Gruss
Pulpapex

Nachtrag: sowas macht z.B. typsichere Collections möglich. Eine Collection-Klasse implementiert das IList-Interface mit seinen allgemeinen Methoden interface-explizit. Da diese in der Klasse nicht sichtbar sind, können zusätzlich typsichere Versionen der Interface-Methoden angeboten werden.

24.02.2005 - 11:38 Uhr

Dispose ist interface-explizit implementiert - in der Klasse ausgeblendet. Da using das IDisposable-Interface erwartet, funktioniert das so.

24.02.2005 - 10:29 Uhr
// Projekt KoordinatenEditor
// EditorForm bietet ein Changed-Ereignis an.
// Das Projekt hat keine Referenz auf MainForm.
public class EditorForm : Form {

  // Die Daten.
  public object KoordinatenDaten { get; set; }

  protected void OnChanged() {
    if(Changed != null) {
      Changed(this, EventArgs.Empty);
    }
  }

  // Das Ereignis
  public event EventHandler Changed;
}
// Projekt Hauptanwendung
// MainForm abonniert das Changed-Ereignis.
// Das Projekt hat einen Verweis auf die Editor-Dll.
public class MainForm : Form {

  private EditorForm editorForm;

  private void InitializeComponent() {
  
    // ..

    EditorForm editorForm = new EditorForm();
    editorForm.Changed += new EventHandler(HandleEditorChanged);
  }

  // Ereignishandler für Änderungen im Koordinaten-Editor.
  private void HandleEditorChanged(object sender, EventArgs e) {
    AktualisiereAnsicht();
  }

  // Die Ansicht des Hauptfensters aktualisieren.
  public void AktualisiereAnsicht() {
    object daten = this.editorForm.KoordinatenDaten;
    // ..
  }
}
24.02.2005 - 10:14 Uhr

OwnerForm in editorForm.ShowDialog(ownerForm) ist nur das Fenster, für das ein Dialog modal angezeigt wird. Um editorForm nicht modal anzuzeigen, ruft man nur Show auf.

Wie die Hauptanwendung bei Änderungen im Editor aktualisiert wird, musst du selbst programmieren. Am besten stellt die Editor-Form Ereignisse zu Verfügung, die die Haupt-Form abonniert [Edit: die Ereignisse]. Wird ein Ereignis ausgelöst, holt sich die Haupt-Form die Änderungen ab und aktualisiert die eigene Ansicht. Der Editor weiss so noch immer nicht, dass es eine Hauptanwendung gibt.

24.02.2005 - 09:47 Uhr

Ist so eine Trennung möglich?

// KoordinatenEditor - Anwendungsprojekt
public class KoordinatenEditor {

  public static void Main() {
    KoordinatenEditorForm editor = new KoordinatenEditorForm();
    Application.Run(editor);
  }
}

// KoordinatenEditor - Dll-Projekt
public class KoordinatenEditorForm : Form {
}

Dann könnte der Koordinateneditor standalone und aus der Hauptanwendung heraus geöffnet werden.

// Projekt Hauptanwendung
public class HauptanwendungForm : Form {

  public void ShowKoordinatenEditor() {
    KoordinatenEditorForm editor = new KoordinatenEditorForm();
    editor.ShowDialog(this);
  }
}

Im Projekt der Hauptanwendung wird nur Dll des Karteneditors referenziert. Die Weiterentwicklung des Editors kann weiterhin losgelöst erfolgen. Er ist auch nicht auf die Hauptanwendung angewiesen.

Wenn das so nicht geht, ist .Net Remoting die nächsteinfachste Möglichkeit. Um bei Remoting keine Abhängigkeiten in die Projekte zu bekommen, wird noch ein weiteres Projekt benötigt. In dieses kommen alle Typen, die von beiden Projekten verwendet werden - hauptsächlich Interfaces und Daten-Klassen. Remoting erfordert einigen Einarbeitungsaufwand. Am besten erst ein paar Testanwendungen entwickeln, bevor das in die richtigen Projekte eingebaut wird.

Gruss
Pulpapex

24.02.2005 - 09:07 Uhr

Ich habe den Eindruck, dass der Koordinateneditor nur ein zweites Fenster in der Hauptanwendung ist. Spricht da was dagegen?

24.02.2005 - 00:30 Uhr

Hi OlBo

Zu 1.: die Hashtables sollten auf jeden Fall in einer oder mehreren Klassen gekapselt werden, ... so dass sich eine Schnittstelle bietet, die genau auf den Anwendungsfall zugeschnitten ist. Eine Hashtable bietet so viele Methoden und alle sind allgemein gehalten. Nach ein paar Monaten weisst du nicht mehr was da gespeichert werden soll und was man machen darf und was nicht. Hashtables also hinter einer ordentlichen Schnittstelle verstecken. So was wie:

class AuftragVerwaltung {
  public void AddAuftrag(Auftrag a) {}
  public void RemoveAuftrag(Auftrag a) {}
  public Auftrag LookupAuftrag(string name) {}
}

(Ist nur ein Beispiel zur Veranschaulichung. Es soll keine Anleitung sein wie so eine Schnittstelle aussieht.)

Zu 2.: ist der Koordinateneditor auch eine .Net-Anwendung? Wenn ja, könnte das Fenster des Koordinateneditors in der Hauptanwendung geöffnet werden. Die Hauptform würde die Editor-Form öffnen, die Daten laden und einer Editor-Form-Eigenschaft zuweisen. Fertig.

Ist der Koordinateneditor zwar eine .Net-Anwendung, er soll aber als eigenständiger Prozess laufen, ist Remoting wahrscheinlich die richtige Wahl. Es ist aufwändiger, aber doch sehr elegant und einfach. Der Code unterscheidet sich nur unwesentlich vom Code des ersten Ansatzes.

Wenn es keine .Net-Anwendung ist, wird es kompliziert. Da kann ich nur aufzählen was mir an Kommunikationsmitteln so einfällt. Vielleicht ist ja was dabei:*.Net Remoting mit XmlSerializer (SOAP) *Sockets *Windows Messages *COM Interop / PInvoke

Gruss
Pulpapex

23.02.2005 - 23:36 Uhr

Das ist mir gleich zu Anfang aufgefallen. Die Beschreibung passt nicht zum Code und am Code ist nicht zu erkennen was er darstellen soll - weil Code in Ereignishandler geschrieben wird und weil wirklich alle Bezeichner nichtssagend sind.

Also bevor es sich überhaupt lohnt da nochmal drüber zu schauen, sollte ne aktuelle Version erstmal leserlich mit Kommentaren gepostet werden - wo Code und textuelle Beschreibung auch zusammenpassen.

23.02.2005 - 14:25 Uhr

Also ich schreibe die öffnende Klammer lieber in die gleiche Zeile (allerdings komme ich auch aus der Java-Sektion 😉 )

Wie sieht es denn hiermit aus?

if(foo > 4)
{
  foo = 5;
}
else if(foo < 1) 
{
  foo = 4;
}
else
{
  foo = 0;
}

Mir ist das zu lang. Ich schreibe es lieber kompakt als:

if(foo > 4) {
  foo = 5;
} else if(foo < 1) {
  foo = 4;
} else {
  foo = 0;
}

Mit Kommentaren würde es so aussehen:

// Fall 1
if(foo > 4) {
  foo = 5;

// Fall 2
} else if(foo < 1) {
  foo = 4;

// Default
} else {
  foo = 0;
}

Zwar steht der Kommentar, wenn man es ganz genau nimmt, im falschen Block, aber es ist trotzdem gut lesbar.

Wenn man die Code-Konventionen beachtet (nach denen öffnende Klammern in neue Zeilen gehören) und vor jedem Kommentar eine Leerzeile lässt, sieht das erste Beispiel mit Kommentaren so aus.

// Fall 1
if(foo > 4)
{
  foo = 5;
}

// Fall 2
else if(foo < 1) 
{
  foo = 4;
}

// Default
else
{
  foo = 0;
}

Eindeutig zu lang und nicht besonders gut leserlich, finde ich.

Gruss
Pulpapex

23.02.2005 - 10:57 Uhr

Late-Binding ist ein Grundkonzept in jeder objekt-orientierten Runtime, Stichwort virtuelle Methoden. Du verwendest es ständig, ohne es zu merken.

23.02.2005 - 10:51 Uhr

Hi Scarface,

So konvertiert man ein byte-Array in einen String.

byte[] byteArray = // ..
string s = Encoding.ASCII.GetString(byteArray);

Gruss
Pulpapex

22.02.2005 - 22:08 Uhr

Hi Capi,

unterstützt CF Control.WndProc oder das IMessageFilter-Interface? Wenn ja, könnte dir dieser Thread weiterhelfen:
MessageFilter - Wert an Formular übergeben

Ansonsten habe ich noch einen Artikel gefunden:
Add Keyboard Support to Compact Framework Apps by Trapping Windows Messages

Gruss
Pulpapex

22.02.2005 - 20:30 Uhr

Ich habe mal schnell einen Performanztest zum Vergleichen von Regex mit String.IndexOf geschrieben.

class RegexVsIndexOf {

	static void Main(string[] args) {

		int count = 2000000;
		Regex indexOfRegex = new Regex("Test", RegexOptions.Compiled);

		string text = "Das ist ein etwas längerer Text. " +
				  "Irgendwo kommt das Wort Test drinnen vor.";

		CodeTimer codeTimer = CodeTimer.GetByName("codeTimer");
		codeTimer.Start();
		for(int i = 0; i < count; i++) {
			int index = indexOfRegex.Match(text).Index;
		}
		codeTimer.Stop();
		Console.WriteLine("Regex: " + codeTimer.TimeString + " s");

		codeTimer.Reset();
		codeTimer.Start();
		for(int i = 0; i < count; i++) {
			int index = text.IndexOf("Test");
		}
		codeTimer.Stop();
		Console.WriteLine("IndexOf: " + codeTimer.TimeString + " s");
	}
}

Ergebnis:

Regex:   00:01:796 s
IndexOf: 00:03:984 s

Man sieht, selbst im einfachsten aller möglichen Fälle ist ein Regex schon schneller. Dürfte sehr schwierig sein, einen Regex mit eigenem Code zu schlagen. Besonders, wenn das Problem komplizierter wird.

Ist eigentlich merkwürdig. Warum wird IndexOf dann nicht mit einem Regex implementiert? ... Frage schon selbst beantwortet ... weil der erst kompiliert werden müsste was schon wieder länger dauert.

Gruss
Pulpapex

Ps: Bevor jemand fragt, CodeTimer ist meine eigene Klasse.

22.02.2005 - 19:59 Uhr

Mit Equals(null) vergleichen geht nicht. Der Equals-Vergleich würde entweder false zurückliefern oder eine NullReferenceException auslösen. Deshalb mit == vergleichen.

Wenn es wirklich um die Controls.Focus-Methode geht (so wie es aussieht), ist es besser auf die Control-Klasse zu testen, so wie schon von suny und herbivore vorgeschlagen.

// So
if(sender is Control) {
  Control c = (Control)sender;
  c.Focus();
}

// Oder so
Control c = sender as Control;
if(c != null) {
  c.Focus();
}
22.02.2005 - 19:24 Uhr

Mit dem Type-Objekt aus GetType() können definierte Methoden abgefragt werden. Nennt sich Reflection.

MSDN: Type.GetMethod Method

Gruss
Pulpapex

22.02.2005 - 17:47 Uhr

Ich würde die doppelten Elemente nicht durch Entfernen aussortieren. Erstens muss ständig der Index in der for-Schleife angepasst werden und zweitens ist es wenig performant, Elemente aus einer ArrayList zu entfernen. Jedes Mal, wenn ein Element entfernt wird, müssen alle nachfolgenden Elemente um eine Position umkopiert werden.

Besser ist eine neue Liste aufzubauen. Foreach-Schleife: wenn ein Element nicht in der Hashtable ist, kommt es in die neue Liste und in die Hashtable. Wenn es das selbe ArrayList-Objekt sein muss, kann man im Anschluss alle Elemente wieder umkopieren.

Gruss
Pulpapex

22.02.2005 - 07:58 Uhr

Das müsste es eigentlich sein. Du hast wahrscheinlich ein neues Projekt angelegt und die DirectX-Verweise vergessen. Schau mal in deinen anderen Projekten. Box und Texture befinden sich zusammen mit Mesh im Microsoft.DirectX.Direct3D-Namespace.

Gruss
Pulpapex

21.02.2005 - 21:53 Uhr

Warum nochmal in einen String wandeln?
Ist doch einfacher so zu testen:

byte b0 = byteArray[0];
if(b0 == (byte)0x50) {
  break;
}
21.02.2005 - 21:38 Uhr

Es wird daran liegen, dass der String noch weitere, nicht sichtbare Zeichen enthält (\r\n). Lass dir mit string.Length die Länge ausgeben.

... oder ist byteString etwa ein String? .. nee, kann nicht sein.

Im Zweifelsfall einfach mal den Debugger verwenden.

Gruss
Pulpapex

21.02.2005 - 14:08 Uhr

Original von Marcel

  1. In einem Grafikprogramm eine PNG-Datei erstellen, die transparente Anteile hat. Diese wird dann die Funktion einer Maske haben.

Hast du das ausprobiert? Ich glaube man muss trotzdem noch die Form.TransparencyKey-Eigenschaft festlegen, so wie es in dem Link von Noodles beschrieben ist.

Gruss
Pulpapex

21.02.2005 - 09:19 Uhr

Das bekommt man mit einer normalen ListBox hin. Allerdings müssen die einzelnen Elemente mit listBox.OwnerDraw = DrawMode.OwnerDrawFixed selbst im DrawItem-Ereignis gezeichnet werden.

Hier der Link zur DrawMode-Enumeration, enthält auch ein Beispiel:
DrawMode Enumeration

Gruss
Pulpapex

20.02.2005 - 22:46 Uhr

Das ist kein Problem, das ist ein Workaround für ein Problem, dessen Ursache du noch nicht gefunden hast. Ich weiss jedoch noch nicht mal wie sich das Problem äußert. Wird in der Zeile z.B. eine NullReferenceException ausgelöst oder was passiert da?

Nochmal zu dem Code:
Du sagst der lädt die Orte in listBox1.

listBox1.Items.AddRange(new object[] {usr[4]});

Gleichzeitig soll aber schon ein Eintrag in listBox1 selektiert sein.

String auswahl2==listBox1.SelectedItem.ToString(); // (da ist ein '=' zu viel.)

Das passt doch irgendwie nicht zusammen. Irgendwie fehlt dieser Teil:

Nun wählt der User den Ort aus und klickt auf ein OK Button

20.02.2005 - 22:10 Uhr

Hast du da nicht irgendwas falsch programmiert, wenn sich das so äußert? Mir scheint du fliegst rückwärts. 😉
Ändere doch mal in camera.Orientation die Vorzeichen aller Vektorkomponenten. Das sollte die Blickrichtung umkehren. Wenn die Drehrichtung dann nicht mehr stimmt, müssen die Vorzeichen im Quarternion geändert werden.

Gruss
Pulpapex

20.02.2005 - 22:00 Uhr

Es sieht nach einem "Strong Names"-Problem aus. Woran das liegt ist die Frage. Eigentlich sollte es funktionieren, wenn die DirectX-Dlls mitgeliefert werden, gegen die compiliert wurde. Kann es sein, dass im Projekt DirectX-Verweise aus dem GAC eingebunden sind und du ganz andere Dlls (mit anderer Version) mitlieferst?

Gruss
Pulpapex

20.02.2005 - 21:48 Uhr

Original von alf468
Nur leider gibt es da Probleme mit dem auswahl2==listBox1.SelectedItem.ToString();

Was gibt es denn da für Probleme? In jedem Fall solltest du die Abfrage aus der while-Schleife rausziehen und dazu prüfen ob überhaupt etwas selektiert ist.

//if (usr[5] == "1")
//{
listBox1.Items.AddRange(new object[] {usr[4]});

Der Code kommt mir sehr suspekt vor. Du fügst beim Laden der Namen-ListBox Elemente zur Orte-ListBox hinzu?

Gruss
Pulpapex

20.02.2005 - 21:26 Uhr

In der MSDN-Beschreibung zu System.IO.File ist ein Beispiel mit dabei wie man die Klassen File und StreamReader verwendet. Das Beispiel liest eine Datei zeilenweise mit StreamReader.ReadLine ein, was gut zu deiner Trace-Datei passen müsste.

Die einzelnen Textzeilen können meiner Meinung nach einfacher und flexibler mit einem regulären Ausdruck zerlegt werden. Das könnte z.B. so aussehen:


// Folgende Tracezeile mit dem beschriebenen Muster auswerten.
// Tracezeile: "2005/02/20 21:00 KATEGORIE Das ist eine Traceausgabe."
//
// tracePattern: (.{10})\\s+(.{5})\\s+(\\S+)\\s+(.*)
// Gruppen:      (group1)  (group2) (group3)(group4)
//
// group1: Datum     - 10 beliebige Zeichen.
// \\s+   :           - ein oder mehr Leerzeichen.
// group2: Zeit      - 5 beliebige Zeichen.
// \\s+   :           - ein oder mehr Leerzeichen.
// group3: Kategorie - alles ausser Leerzeichen.
// \\s+   :           - ein oder mehr Leerzeichen.
// group4: Text      - was noch übrigbleibt.
string tracePattern = @"(.{10})\\s+(.{5})\\s+(\\S+)\\s+(.*)";
Regex traceRegex = new Regex(tracePattern);

// Zu parsende Textzeile.
string traceLine = "2005/02/20 21:00 KATEGORIE Das ist eine Traceausgabe."

// Textzeile zerlegen in Datum, Zeit, Kategorie und Text.
Match m = traceRegex.Match(traceLine);
if(m.Success) {
  string datum     = m.Groups[1].Value;
  string zeit      = m.Groups[2].Value;
  string kategorie = m.Groups[3].Value;
  string text      = m.Groups[4].Value;
}

Kurz zur Erläuterung: Ausdrücke in Klammern sind Gruppen, die können im Ergebnis direkt abgefragt werden. Ein einfacher Punkt entspricht einem beliebigen Zeichen. Um einen richtigen Punkt zu finden, verwendet man ".". Der Ausdruck \s entspricht einem Leerzeichen oder einem anderen Whitespace (\t,\r,\n). Der Ausdruck \S entspricht allem außer einem Whitespace. +, * und {zahl} sind Quantifizierer, sie geben die Häufigkeit an wie oft der davor stehende Ausdruck vorkommen soll. Genaueres bitte dem schon oben angegebenen Link entnehmen: .NET Framework Regular Expressions

Gruss
Pulpapex

20.02.2005 - 03:05 Uhr

Mit Suchmuster meinst du wahrscheinlich reguläre Ausdrücke. Das .Net-Framework verwendet eine etwas aufgebohrte Posix Syntax. Man kann z.B. Gruppen benennen. Ansonsten ist alles wie bei anderen Engines - Perl, Java, kaum Unterschiede.

Zum Einlesen von Textdateien gibt es System.IO.File und System.IO.StreamReader. Man muss ein Encoding angeben für die Zeichenkodierung. Für reguläre Ausdrücke gibt es den System.Text.RegularExpressions-Namespace.

Beispiele für die Anwendung von regulären Ausdrücken gibt es im MSDN:
.NET Framework Regular Expressions

Gruss
Pulpapex

18.02.2005 - 22:28 Uhr
Pythagoras
a^2 + b^2 = c^2

Eingesetzt
a = x
b = x+1
c = x+2

Quadratische Gleichung
x^2 + (x+1)^2 = (x+2)^2
x^2 - 2x - 3 = 0

Lösung
x1 = -1
x2 =  3
\=======

Quadratische Gleichungen haben bekanntlich immer genau zwei Lösungen.

Gruss
Pulpapex

18.02.2005 - 18:39 Uhr

Doch, gibt es.

Code Access Security

Ich hatte es mir mal durchgelesen (verwendet noch nicht). Es funktioniert derart, dass alle Methoden im Aufrufstack berechtigt sein müssen. Sie werden alle nacheinander durchgecheckt, weshalb die Angabe von CodeAccess-Attributen die Ausführungsgeschwindigkeit beeinträchtigt. Zumindest lässt sich festlegen, dass nur eine ganz bestimmte Assembly eine Methode aufrufen darf, auf Klassen- und Methode-Ebene geht es glaube ich auch.

Gruss
Pulpapex

18.02.2005 - 17:31 Uhr

Was auch noch geht, ist Foo(object) in ein Interface auszulagern und dieses Interface in B interface-explizit zu implementieren. Dadurch wird die Methode in der Klasse ausgeblendet und es dürfte nur noch A.Foo(int) übrigbleiben. Zum Zugriff auf B.Foo(object) müsste die Klasse zuvor ins Interface gecastet werden.

public interface IB {
  void Foo(object v);
}

public class B : IB {
  void IB.Foo(object v) { }
}
18.02.2005 - 17:10 Uhr

Nochmal die Frage, übergibst du nun object oder wirklich int wie im Code angegeben?

object v = 7;
int w = 7;
Foo(v);   // Ruft B.Foo(object) auf.
Foo(w);   // Ruft A.Foo(int) auf.

Wie gesagt, entscheidet der Compiler welche Methode aufgerufen wird. Und der entscheidet anhand des Variablentyps - er kann ja nicht wissen was drin ist.

Ich kann das hier leider nicht ausprobieren, bin mir aber fast sicher, dass das so ist.

18.02.2005 - 16:37 Uhr

Weil du da eine ObjectToInt-Methode definiert hast. Kann es sein, dass du in Wirklichkeit sowas versuchst?

object v = 7;
Foo(v);

Dann wäre es klar, dass B.Foo(object) aufgerufen wird. Die Entscheidung, welche Methode aufzurufen ist, wird bei nicht virtuellen Methoden alleine vom Compiler gefällt. Da v vom Typ object ist, wird B.Foo(object) aufgerufen.

Mit:

Foo((int)v);

sollte eigentlich A.Foo(int) aufgerufen werden. Bin mir aber nicht 100% sicher ob das auch auf Methoden, definiert in verschiedenen Klassen, zutrifft. Aber denke schon.

18.02.2005 - 16:10 Uhr
public class C : B
{
  public void DoSomething()
  {
    Foo( 7 );
  }
}

Ich werde mich wahrscheinlich irren, aber wird hier nicht schon A.Foo aufgerufen? Wie du schon selbst gesagt hast, passt 7 besser zur A.Foo-Methode mit int-Parameter als zu B.Foo mit object-Parameter und müsste deshalb bevorzugt werden.

Gruss
Pulpapex

17.02.2005 - 14:39 Uhr

Stimmt,
wenn der Type schon zur Compilezeit bekannt ist, ist das die einfachste Lösung. Dann aber ohne das typeof, zweites Argument von is muss ein Type sein, kein Type-Objekt.

17.02.2005 - 14:12 Uhr

Ich habe das Problem glaube ich immer noch nicht erkannt. Gibt doch mal ein Beispiel an wo IsAssignableFrom true zurückgibt, aber trotzdem nicht zugewiesen werden kann. Oder schildere mal deinen eigentlichen Problemfall, den du gerade versuchst zu lösen ... was klappt nicht.

Oder sag was hieran falsch ist:

private bool checkType(Type myType, object myValue)
{
  Type myValueType = myValue.GetType();
  bool assignable = myType.IsAssignableFrom(myValueType);
  return assignable;
}

// Anwendung.

// true.
bool assignable = checkType(typeof(string), "abc");
// false.
assignable = checkType(typeof(System.Int32), "xyz");
17.02.2005 - 13:15 Uhr

Zeig mal ein Beispiel wo eine Zuweisung eine Exception auslöst obwohl IsAssignableFrom true zurückgibt. Eigentlich sollte das immer funktionieren, wenn ich jetzt keinen Denkfehler habe.

Was Probleme macht, ist das hier. Zwei Felder a und b sind zwar vom Typ object, ihre Werte sind jedoch string und string[]. Der Test mit IsAssignable liefert deshalb false:

public class AssignableTest {

  private object a = "string";
  private string[] b = new string[5];

  public void Assign() {

    // Liefert false, da einer String-Variablen kein String-Array zugewiesen werden kann.
    if(a.GetType().IsAssignableFrom(b.GetType()) {
      a = b;
    }

    // So in der Art müsste es funktionieren.
    Type thisType = this.GetType();
    FieldInfo aField = thisType.GetField("a", BindingFlags.Instance | BindingFlags.NonPublic);
    FieldInfo bField = thisType.GetField("b", BindingFlags.Instance | BindingFlags.NonPublic);
    if(aField.FieldType.IsAssignableFrom(bField.FieldType) {
      a = b;
    }
  }
}

Ich hoffe das hast du gemeint.

Gruss
Pulpapex

16.02.2005 - 23:44 Uhr

Ich sehe gerade, dass die XML-Spezifikation das encoding-Attribut nicht unbedingt vorschreibt. Es kann auch weggelassen werden.

Extensible Markup Language (XML) 1.0 (Third Edition) # [23] XMLDecl

Die Chance besteht also, das Attribut wegzubekommen. Nicht mal das <?xml?>-Element muss angegeben werden, (wenn ich die Spec richtig deuten kann).

Es kann aber trotzdem sein, dass es in .Net nicht vorgesehen ist, diese Angabe benutzerdefiniert wegzulassen (weiss ich nicht). Als letzte Möglichkeit bleibt dann immer noch, in einen MemoryStream zu serialisieren und dort Anpassungen vorzunehmen.

16.02.2005 - 23:20 Uhr

Du kannst dem XmlWriter, der im XmlSerializer-Konstruktor übergeben wird (oder den anderen Objekten, die in den verschiedenen Überladungen auftauchen), das zu verwendende Encoding mitgeben. Ich denke mal das wird dann auch im <?xml?>-Element eingetragen.

Das ganze <?xml?>-Element oder auch nur das encoding-Attribut wirst du nicht wegbekommen, denn sowas gehört zu wohlgeformtem XML und muss vorhanden sein.

Gruss
Pulpapex

16.02.2005 - 16:04 Uhr

Jetzt weiss ich was du meinst. Du möchtest genau den Fall haben, dass sich Variablen trotz Zuweisung nicht gegenseitig die Werte ändern. Tja, da kann ich nur sagen, das Ding nennt sich Referenztyp. Das muss man einfach so hinnehmen, dass bei der Zuweisung eines Referenztypes keine Kopie erstellt wird.

Wenn man kopieren möchte, muss die Klasse eine Methode dafür anbieten, Stichwort: ICloneable-Interface. Eine flache Kopie erhält man über die geschützte Object.MemberwiseClone-Methode. Die dürfte in etwa dem Kopieren von C++ Klassen entsprechen.

public class Kopierbar : ICloneable {

  public object Clone() {
    return this.MemberwiseClone();
  }
}

// Anwendung.
Kopierbar a = new Kopierbar();
Kopierbar b = (Kopierbar)a.Clone();