Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von Pulpapex
Thema: Problem bei Typumwandlung
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

die Umwandlung zu sbyte würde ich weglassen. Bringt nichts.

Die heutigen 32 Bit Rechner kommen halt besser mit 32 Bit zurecht. Alle Zwischenergebnisse der Rechnung sind 32 bit. Der cast bedeutet nur zusätzlichen Aufwand. Und Speicher sparst du dadurch auch nicht. Gerade mal 3 Byte. Der Cast nach sbyte benötigt wahrscheinlich mehr als 3 Byte IL-Code. Selbst ein bool belegt intern 32 bit.

Bei einem grossen Array könnte man vielleicht nochmal überlegen.


Gruss
Pulpapex.

Thema: Postback
Am im Forum: Web-Technologien

Es wird alles übertagen was sich mit dem Button in der selben Html-Form befindet. Du könntest die Webseite in zwei Forms aufteilen. Dann werden nur die Daten der Form übertragen, die submitted wird.


Gruss
Pulpapex

Thema: Methode mit mehreren Rückgabewerten
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Per Klasse oder Struct, Methoden können nur einen Rückgabewert haben.

public struct DarstellungInfo {
   public string Name;
   public string L;
   public string D;
   public string B;
}

Gruss
Pulpapex

Thema: Erkenntnis MVC? neuer Ansatz?
Am im Forum: Rund um die Programmierung

Mit der deutschen Wikipedia-Version von MVC stimme ich überhaupt nicht überein. Dort implementiert der Controller die Anwendungslogik. Das Model hält nur die Daten.

Diese Trennung von Logik und Daten macht keinen Sinn. Ich hatte das schon mal hier irgendwo erläutert. Was nutzt einem die Logik im Controller? Der Controller kennt die View! Wenn man eine schlanke Kommandozeilen-Version für sein GUI-Programm anbieten möchte, geht das nicht. Man muss immer die fette GUI mit ausliefern, weil die Anwendungslogik von ihr abhängt.

Mein Beispiel sieht ganz anders aus. Dort stellt der Controller nur Glue-Code ohne eigene Logik da. Er konfiguriert Model und View, reagiert auf deren Ereignisse und delegiert sie als Aktionen weiter (Closing-Event -> Login -> userManager.Login -> e.Cancel).

Möchte man Model oder View ersetzen, muss man auch immer den Controller mit ausgetauschen. Also die App.exe muss neu geschrieben werden. Ziel ist es deshalb den Code im Controller möglichst klein und einfach zu halten, damit der Austausch nicht zu viel Aufwand macht.

herbivore, in deinem Diagamm ist nicht zu erkennen, dass die Benutzer-Interaktionen eigentlich über Ereignisse der View mitgeteilt werden: okButton.Click - der Benutzer hat den Schalter gedrückt. Auch sieht es so aus, als würde das Model die View kennen. Das liegt aber nur an der Darstellung, die sehr von der Programmierersicht abstrahiert. Eigentlich soll dein und mein Diagramm genau das selbe darstellen. Der Controller reagiert auf Ereignisse und bedient das Model. Bei mir bedient er noch die View, z.B. öffnet er Dialoge oder schaltet Sichten um. Model-Aktualisierungen kommen auch bei mir, wenn möglich direkt ohne Umweg über den Controller zur View, per Event oder bound Properties.


Gruss
Pulpapex

Thema: Erkenntnis MVC? neuer Ansatz?
Am im Forum: Rund um die Programmierung

Hi michaelschuler,

was du da beschreibst, ist in etwa der normale, saubere MVC-Ansatz.

Es gibt Views,
- "dumme" Windows-Controls/Forms, in die der Benutzer was eingibt.

Model-Klassen,
- Datenhaltung und Anwendungslogik.

Und es gibt Controller-Klassen
- die eigentliche Anwendung (aber hat enthält keine/wenig Programmlogik).
- Sie verwendet die Model-Klassen und Views.
- Sie verknüpfen und initialisieren das Ganze.

Beispiel - Benutzer einloggen.

// GUI-Komponente, kennt nur sich selbst.
public class LoginDialog : Form {
   public string User { get; set; }
   public string Password { get; set; }
   public string LoginErrorMsg { get; set; }
}

// Model-Klasse, kennt nur sich selbst.
public class UserManager {
   public bool Login(string user, string password);
   public string LoginErrorMsg { get; }
}

// Controller (Anwendung), verwendet LoginDialog und UserManager.
public class App {

   private bool loggedIn = false;
   private LoginDialog loginDialog;
   private UserManager userManager;

   public static void Main() {
      new App().Login();
   }

   public App() {

      loginDialog = new LoginDialog();
      loginDialog.Closing += new CancelEventHandler(HandleClosing);

      userManager = new UserManager();
   }

   public void Login() {
      loginDialog.ShowDialog();
      Console.WriteLine("Logged In: {0}", loggedIn);
   }

   private void HandleClosing(object sender, CancelEventArgs e) {
      e.Cancel = !DoLogin();
   }

   private bool DoLogin() {

      // (Edit: hab ich aus dem HandleClosing rausgezogen. 
      // Ist hier besser aufgehoben).
      if(loginDialog.DialogResult != DialogResult.Ok) {
         loggedIn = false
         return true; // e.Cancel = false;
      }

      loggedIn = userManager.Login(loginDialog.User, loginDialog.Password);
      if(!loggedIn) {
          // Kann man auch über ein "bound property" realisieren.
          userDialog.LoginErrorMsg = userManager.LoginErrorMsg;
      }
      return loggedIn;
   }

}
(Hier werden wahrscheinlich Syntaxfehler drin sein, hab's nur schnell geschrieben. Geht nur ums Prinzip)

Im Anhang das Ganze nochmal als Diagramm. Gestrichelte Linien stellen Ereignisse da. Die durchgezogenen Linien sind die Assoziationen/Abhängigkeiten.


Gruss
Pulpapex

Thema: Ungültige Länge für einen Base-64-Zeichenarray
Am im Forum: Web-Technologien

Zitat
Wo kommt dieser Lange String überhaupt her?
Das sind irgendwelche Text- oder Binärdaten, die Base64-kodiert per Http übertragen werden. Ich hab nicht so viel Ahnung von ASP.NET. Wenn ich die Doku richtig deute, dann ist das der Inhalt der Formularfelder auf der Webseite. Der Browser schickt sie in einem Hidden-Field namens ViewState per POST an die Server-Anwendung. (Find ich ein bisschen daneben, wenn das wirklich so gehandhabt wird, aber naja.)

Du kannst den String ja mal manuell dekodieren, um zu sehen was drin steht. Wie es geht, steht in der Fehlermeldung. Wenn sie erneut auftaucht, ein '=' an den String anhängen und es nochmal probieren, usw. bis es klappt.

Thema: Ungültige Länge für einen Base-64-Zeichenarray
Am im Forum: Web-Technologien

Hallo,

vielleicht hilft dir die Wikipedia-Seite zur Base64-Kodierung weiter.

Die Gesamtzahl kodierter Bytes muss durch 3 teilbar sein. Die Anzahl der in der Kodierung verwendeten Zeichen muss durch 4 teilbar sein. Wenn es nicht passt, wird mit '=' aufgefüllt.

dDwxMTI3MTUxNjAxO3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDE+O2k8Mj47aTwzPjtpPDQ+Oz47bDx
0PHA8cDxsPFZpc2libGU7PjtsPG88Zj47Pj47Pjs7Pjt0PHA8cDxsPFZpc2libGU7PjtsPG88Zj
47Pj47Pjs7Pjt0PHA8cDxsPFZpc2libGU7PjtsPG88dD47Pj47PjtsPGk8MT47PjtsPHQ8dDw7d
DxpPDMzPjtAPFRpc2NoIDE7VGlzY2ggMjtUaXNjaCAzO1Rpc2NoIDQ7VGlzY2ggNTtUaXNjaCA2
O1Rpc2NoIDc7VGlzY2ggODtUaXNjaCA5O1Rpc2NoIDEwO1Rpc2NoIDExO1Rpc2NoIDEyO1Rpc2N
oIDEzO1Rpc2NoIDE0O1Rpc2NoIDE1O1Rpc2NoIDE2O1Rpc2NoIDE3O1Rpc2NoIDE4O1Rpc2NoID
E5O1Rpc2NoIDIwO1Rpc2NoIDIxO1Rpc2NoIDIyO1Rpc2NoIDIzO1Rpc2NoIDI0O1Rpc2NoIDI1O
1Rpc2NoIDI2O1Rpc2NoIDI3O1Rpc2NoIDI4O1Rpc2NoIDI5O1Rpc2NoIDMwO1Rpc2NoIDMxO1Rp
c2NoIDMyO1Rpc2NoIDMzOz47QDxUaXNjaCAxO1Rpc2NoIDI7VGlzY2ggMztUaXNjaCA0O1Rpc2N
oIDU7VGlzY2ggNjtUaXNjaCA3O1Rpc2NoIDg7VGlzY2ggOTtUaXNjaCAxMDtUaXNjaCAxMTtUaX
NjaCAxMjtUaXNjaCAxMztUaXNjaCAxNDtUaXNjaCAxNTtUaXNjaCAxNjtUaXNjaCAxNztUaXNja
CAxODtUaXNjaCAxOTtUaXNjaCAyMDtUaXNjaCAyMTtUaXNjaCAyMjtUaXNjaCAyMztUaXNjaCAy
NDtUaXNjaCAyNTtUaXNjaCAyNjtUaXNjaCAyNztUaXNjaCAyODtUaXNjaCAyOTtUaXNjaCAzMDt
UaXNjaCAzMTtUaXNjaCAzMjtUaXNjaCAzMzs+Pjs+Ozs+Oz4+O3Q8cDxwPGw8VmlzaWJsZTs+O2
w8bzxmPjs+Pjs+O2w8aTwxPjtpPDM+O2k8NT47aTw3PjtpPDk+O2k8MTM+O2k8MTk+O2k8MjU+O
z47bDx0PHA8cDxsPFRleHQ7PjtsPEJhcmNvZGU6IDEwMDQ4Oz4+Oz47Oz47dDxwPHA8bDxUZXh0
O1Zpc2libGU7PjtsPDEwMDQ4O288Zj47Pj47Pjs7Pjt0PHA8cDxsPFZpc2libGU7PjtsPG88Zj4
7Pj47Pjs7Pjt0PHQ8O3Q8aTw4PjtAPENvY2EgQ29sYSAgMCwzM2wgIDAsNTAg4oKsIDtGYW50YS
BaaXRyb25lIDAsNTBsICAxLDAwIOKCrCA7SGFzc2Vyw7ZkZXIgMCw1MGwgIDIsMDAg4oKsIDtLc
m9tYmFjaGVyIDAsNTBsICAzLDMzIOKCrCA7U3ByaXRlIDAsNTBsICAxLDAwIOKCrCA7S2FmZmVl
IDAsMjBsICAxLDAwIOKCrCA7TGF0dGUgTWFjY2hpYXRvIDAsMzNsICAxLDAwIOKCrCA7V2Fzc2V
yIDAsMjBsICAwLDUwIOKCrCA7PjtAPENvY2EgQ29sYSAgMCwzM2wgIDAsNTAg4oKsIDtGYW50YS
BaaXRyb25lIDAsNTBsICAxLDAwIOKCrCA7SGFzc2Vyw7ZkZXIgMCw1MGwgIDIsMDAg4oKsIDtLc
m9tYmFjaGVyIDAsNTBsICAzLDMzIOKCrCA7U3ByaXRlIDAsNTBsICAxLDAwIOKCrCA7S2FmZmVl
IDAsMjBsICAxLDAwIOKCrCA7TGF0dGUgTWFjY2hpYXRvIDAsMzNsICAxLDAwIOKCrCA7V2Fzc2V
yIDAsMjBsICAwLDUwIOKCrCA7Pj47bDxpPDA+Oz4+Ozs+O3Q8dDw7O2w8aTwwPjs+Pjs7Pjt0PH
Q8O3Q8aTwxPjtAPDAzIHggMCw1MOKCrCAwLDMzbCBDb2NhIENvbGEgOz47QDwwMyB4IDAsNTDig
qwgMCwzM2wgQ29jYSBDb2xhIDs+Pjs+Ozs+O3Q8cDxwPGw8VmlzaWJsZTs+O

Hier sind es 75 Zeichen pro Zeile mal 28 Zeilen. In der letzten Zeile sind es nochmal 60 Zeichen. Das bedeutet (75*28 + 60) % 4 = 0. Es ist also teilbar. Die Zeilenumbrüche werden bei der Kodierung eingefügt, ansonsten aber ignoriert.

Scheint korrekt zu sein. Wenn es nur auf dem PDA Probleme macht, würde ich einen Bug oder irgend einen Seiteneffekt vermuten.


Gruss
Pulpapex

Thema: Aufgemerkt, warum OOP?
Am im Forum: Rund um die Programmierung

Es gibt Vorteile, aber auch Nachteile, OOP macht nicht immer Sinn. Wenn es beispielsweise wenig Logik und wenig Datenstruktur, dafür aber viele Daten gibt und es auf Geschwindigkeit ankommt, ist Objekt-Orientierung fehl am Platz. Das trifft z.B. auf Datenbank-Massendaten, DSP oder Shader-Programmierung zu.

In deiner Anwendung scheint mir Objektorientierung jedoch hilfreich zu sein, da es eine komplexe Datenstruktur gibt.

Bei OOP geht es ganz allgemein um die Abbildung eines Teils der realen Welt auf Klassen - auf ein sogenanntes Objektmodell. Das Objektmodell ist unabhängig von der Art der Anwendung (Web, Gui, Konsole ...) konzipiert, in der es verwendet wird. Es enthält nur Daten und definiert Operationen auf diesen. Das ganze sollte modular gehalten sein. D.h. das Objektmodell braucht nicht zu wissen, dass es in einer Datenbank gespeichert wird, es gibt einen Datenbank-Service, dem man es übergeben kann. Genauso wenig muss es wissen, dass es eine GUI gibt, die es anzeigt oder eine Druck-Komponente, die es formatiert und ausdruckt, - einen Web-Server, einen Berichtsgenerator usw. Da das Objektmodell so einfach und allgemein gehalten ist. Insbesondere, da es nicht innerhalb der GUI-Klassen implementiert ist, können leicht neue Services hinzuimplementiert werden und es kann in anderen Umgebungen verwendet werden, Ausdrucken per Kommandozeile beispielsweise.

Deine Anwendung liesse sich sauber trennen in App.exe, Core.dll, Gui.dll, und Db.ll. App.exe kennt alle drei Dlls. Core.dll mit dem Objektmodell kennt nur sich selbst. Gui.dll kennt u.U. Core.dll (obwohl es auch möglich ist, die Gui unabhängig vom Objektmodell zu implementieren). Und Db.dll kennt Core.dll.

So stehen einem alle Möglichkeiten offen. Wie schon oben geschrieben, kann man nun Core.dll und Db.dll nehmen, um Webseiten zu rendern oder auszudrucken. Genauso gut ist es auch möglich, Db.dll durch eine WebService.dll ersetzen, um Objektmodell-Daten bei einem WebService anzufordern.

Aber Flexibität und Modularität muss man sich meistens mit mehr Code erkaufen, das stimmt schon. Durch die einfachere, aufgeräumte Schnittstelle und durch die leichtere Wiederverwendbarkeit sollte im Endeffekt der aber Aufwand sinken, hoffentlich.


Gruss
Pulpapex

Thema: Klasse in ByteArray umwandeln
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Gibt es,

das grundlegende Prinzip hierfür nennt sich Serialisierung. Damit ein Objekt serialisiert werden kann muss die Klasse und alle referenzierten Typen das Serializable-Attribut gesetzt (ist bei den meisten .Net-Klassen der Fall). Alternativ kann man auch das ISerializable-Interface implementieren, das ist dann benutzerdefinierte Serialisierung.

Im .Net-Framework wird ein binärer Serialisierer und ein Serialisierer auf Xml-Basis mitgeliefert. Das nur zur Einführung. Ich hoffe du kommst damit weiter.


Gruss
Pulpapex

Thema: Objekt weiterreichen oder statische Klasse anlegen?
Am im Forum: Rund um die Programmierung

Nimm doch einfach einen fertigen Logger. Z.B. die log4j-Portierung Apache log4net.

Benutzt wird log4net so:

public class MyClass {

   // Statische Logger-Instanzen.
   private static ILog log = LogManager.GetLogger(typeof(MyClass));
   private static ILog mailer = LogManager.GetLogger("mailer");

   // Methode, die die Loggers benutzt.
   public void DoSomething() {

      try {
         log.Debug("Debug");

      } catch(Exception ex) {
         log.Error(ex);
      }

      if(seriousError) {
         mailer.Fatal("Serious Error");
      }
   }
}
Die Konfiguration der Logger erfolgt entweder irgendwo bei Programmstart oder wird in einer Xml-Config-Datei hinterlegt. Statt der zwei Logger log und mailer könnte man die Konfiguration auch so anpassen, dass z.B. alles standardmässig in eine Datei geloggt wird, aber ab Stufe fatal auch Mails versendet werden.

Geloggt wird in die sogenannten Appenders - Log-Ziele. Das kann alles mögliche sein, z.B. Mail, Datenbank, Datei, Console, Application Event Log usw. (siehe: log4net-Features). Was genau geloggt wird - Datum, Uhrzeit, Quelle, Meldung usw. - wird in der Appender-Konfiguration per Format-String festgelegt.

@herbivore: am Code-Beispiel sieht man auch den Vorteil von Singletons, gegenüber Klassen, deren Methoden komplett statisch sind. Mit Singletons kann es mehrere Logger-Implementierungen geben und die Anwendung muss nicht wissen welchen sie verwendet. Mit statischen Methoden bräuchte man z.B. einen FileLogger und einen MailLogger, die fest in der Anwendung verdrahtet sind. Auch wäre es nicht möglich zwei verschieden konfigurierte FileLoggers gleichzeitig zu verwenden, falls das mal notwendig sein sollte.


Gruss
Pulpapex

Thema: NHibernate oder eigener Mapper?
Am im Forum: Datentechnologien

Wie meinst du das "die Struktur der Objekte nicht ablegen"? Ein O/R-Mapper macht genau das, er bildet einzelne Klassen auf eine oder mehrere Datenbanktabellen ab. Desweiteren mappt er die Beziehungen zwischen den Klassen: Vererbungsbeziehungen, Assoziationen, 1:n/m:n-Beziehungen (Collections) und noch ein paar andere.

Um die Änderungen eines kompletten Objektgraphen mit (N)Hibernate zu speichern, reicht:

ISerializable id = session.Save(objectGraph);
Um Objektgraph wieder zu laden reicht:

ObjectGraph objectGraph = (ObjectGraph)session.Load(typeof(ObjectGraph), id);

Hinzu kommt die einfache, aber mächtige Anfragesprache HQL. Z.B. kann man sowas schreiben:


// Mapping
// class: Parent, subclasses: Mother, Father
// class: Child

// Alle Mütter, die ein Kind älter als 15 haben.
IList mothers = session.Find(
   "select m from Mother m
   join m.children c
   where c.age > 15");

// Die selbe Anfrage aus entgegengesetzter Richtung.
IList mothers = session.Find(
   "select c.mother from Child c
   where c.age > 15");
HQL-Anfragen werden im Hintergrund in den eingestellten SQL-Dialekt übersetzt. Zumindest Hibernate kommt mit sehr vielen Datenbanksystemen zurecht (bei NHibernate weiss ich es nicht). Man braucht sich also nicht einmal mehr um die verschiedenen SQL-Dialekte zu kümmern.

Ans selber Schreiben solltest du gar nicht erst denken, kann nur schiefgehen. Die Frage ist, ob ein Mapper eingesetzt werden soll oder nicht.

Vorteile:
- weniger Code,
- einfacher, übersichtlicher und konsistent.
- leicht wartbar.
- läuft (wenn getestet) ohne Anpassung auf verschiedenen Datenbanken.

Nachteile:
- langsamer als natives SQL.
- Zwischenschicht, die die Fehlersuche erschwert (sehr viel Magie).
- Mapping-Definition bei vorgegebenem DB-Schema kann sich schwierig gestalten.
- In NHibernate: keine Bulk-Updates. Die kann man aber über die Verbindung von Hibernate direkt an die Datenbank absetzen, wirkt sich nur nicht auf die bereits geladenen Objekte aus.

Thema: Alternativer Regex
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

"eco[_name]" findet nicht "eco" und auch nicht "eco_name", sondern z.B. "eco_".


@jofenchel: neben dem was herbivore geschrieben hat, irritiert mich noch das "+ ecu".

Ganz allgemein; Regexes dynamisch zusammen zu bauen, ist keine gute Idee, ist zu rechenaufwändig. Poste mal paar Beispielzeilen und dazu welche wie gematcht werden sollen und welche nicht (den Regex nicht im CSharp-Codeblock schreiben, der verschluckt die Backslashes).

Thema: Datenübergabe
Am im Forum: Datentechnologien

Hi Rainbird,

so in der Art habe ich das MVC-Pattern auch verstanden.

Konkret zum Controller:
Normalerweise registriert der Controller die View für Model-Ereignisse und umgekehrt (oder er verbindet Daten-bindungsfähige Properties). Ansonsten hat er nicht viel zu tun. Er kann sich auch selbst für die Ereignisse registrieren, wenn ein direktes Verbinden von Model und View nicht möglich ist. Der Code im Ereignishandler sollte dann allerdings so kurz wie möglich sein. Auf keinen Fall darf der Contoller selbst auf Ereignisse reagieren. Er darf nur sehr wenig Logik enthalten.

Für mich ist der Controller nur notwendiger Glue-Code. Wird die View oder das Model wiederverwendet, muss der Controller in jedem Fall neu geschrieben werden.

In der Wikipedia ist das, finde ich, falsch beschrieben. Dort enthält der Controller alle Anwendungslogik. Das Model enthält nur die Daten, aber nicht keine Operationen auf diesen, wie es eigentlich sein sollte.


Wikipedia: Model View Controller

Zitat
Controller

Die Steuerungsschicht realisiert die eigentliche Geschäftsintelligenz und bildet mit Hilfe der anderen Schichten die Prozesse ab. Sie steuert den Ablauf, verarbeitet Daten, entscheidet, welche View aufgerufen wird, etc.

An dieser Stelle driften die Ansichten auseinander. Aber es muss eigentlich falsch sein, ... wenn der Controller die Logik enthält und dazu noch die View kennt, kann die View nicht ohne weiteres ausgetauscht werden. Der Controller kommt ohne die View nicht aus. Das bedeutet, dass alle drei Komponenten eng verbunden sind, was MVC ja gerade verhindern soll.

Also eigentlich müsste der Artikel angepasst werden. Oder gibt es noch andere Sichtweisen?


Gruss
Pulpapex

Thema: Button im IExplorer,... betätigen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Die Fehlermeldung sagt, entweder es fehlt eine using-Direktive oder die Assembly mit der gesuchten WebBrowser-Klasse wird nicht referenziert. In beiden Fällen kann der Type nicht aufgelöst werden.

Compiler Error CS0246


Kann es sein, dass du mit .Net 1.1 programmierst? Da gibt es noch kein WebBrowser Windows-Control.

Thema: Button im IExplorer,... betätigen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Ich würde sagen es kommt drauf an was man als Ergebnis haben möchte. Geht es um die Anzeige der neuen Seite in einem Fenster, ist das WebBrowser-Control besser geeignet. Wenn man die Daten haben möchte, ist es meiner Meinung nach besser mit einem WebClient oder HttpWebRequest den Post- oder Get-Aufruf selbst zu senden. Was anderes macht der Button auch nicht.

Nur der Vollständigkeit halber, das WebBrowser-Control ist der IE in einer COM-Komponente. Das gleiche gibt es auch für Mozilla.

Mozilla ActiveX Control

Thema: Testgetriebene Entwicklung
Am im Forum: Rund um die Programmierung

Zitat
Bakunin
Was ich jetzt nicht ganz verstehe, wieso diese Schritte durchmachen.
Die Schritte darf man nicht so eng sehen. Das sind Beispiele, die erläutern sollen, wie testgetriebene Entwicklung (und Extreme Programming) vom Prinzip her ablaufen.

1. Schritt, die nicht implementierte Eigenschaft sollte im Test fehlschlagen.
2. Schritt, die extremst einfachste Implementierung funktioniert anfangs. Super, reicht erstmal so.
3. Schritt, man programmiert weiter und lässt zwischendurch seine bis dahin entwickelten Tests laufen. Einige Tests werden fehl schlagen. So sieht man sofort, welcher alter Code mit den aktuellen Änderungen nicht mehr zusammen funktioniert und angepasst werden muss. Die in Schritt 2 entwickelte, einfachste Implementierung muss wahrscheinlich etwas ausgebaut werden.

Ziel ist es, so einfachen und primitiven Code wie möglich zu schreiben, der gerade das erledigt, was er soll. Vorkehrungen für etwaiige, zukünftige Anforderungen werden rigoros ausser Acht gelassen. Man kennt sie ohnehin nicht. Ansonsten steckt man viel Aufwand in etwas was später in der Form niemals erforderlich sein wird. Da man aber den Quatsch nicht wieder entfernen möchte, war ja viel Arbeit, versucht man alle notwendigen Änderungen ins geschaffene "Framework" zu integrieren. So steigt der Aufwand für Änderungen langsam ins Unermessliche.

Die einfache Lösung zu programmieren, ist manchmal schwieriger als man denkt. Man muss sich dazu zwingen, pragmatisch und zielgerichtet zu programmieren (und auch viel umzustricken). Am Anfang hat man tolle Ideen, die alle umgesetzt werden müssen. Am besten gleich alle auf einmal. Das Programm, das alles kann! Von dieser Vorstellung muss man sich lösen. Die Beispiele sind deshalb so krass gewählt, damit man sich mehr zusammenreisst und zur einfachsten Lösung für ein Problem strebt. Wenn es konkret erforderlich wird, kann immer noch erweitert werden.


Das ging jetzt eher in Richtung XP als in Richtung Testfälle.
Zu den Testfällen. Ich finde es ist nicht unbedingt notwendig, dass jede einzelne Methode oder Eigenschaft getestet wird. Zu viele Tests sind auch nicht gut, da sie sonst zu häufig angepasst werden müssen. Meiner Meinung nach schreibt man Tests pro Testfall/Szenario, so wie larslovesdotnet es beschrieben hat. Auf der anderen Seite kann das natürlich auch bedeuten, dass man gleich mehrere Tests für eine einzelne Methode/Eigenschaft zu schreiben hat. Da man dabei aber gefordertes Verhalten testet, sollten die Tests einigermassen stabil bleiben.


Gruss
Pulpapex

Thema: Thread am Leben erhalten
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Thread.Sleep oder WaitHandles sind überhaupt nicht notwendig. Das Lesen des Sockets blockiert schon ohne Zutun die Threadausführung, wenn keine Daten gesendet werden. Die Schleife ist nur dafür da, um blockweise Daten zu empfangen und mitzubekommen, wenn der Client die Verbindung schliesst.

Thread.Sleep solltest du wieder ausbauen. Das verlangsamt nur künstlich die Ausführung.

Thema: Rueckgabewerte
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Compare ist hauptsächlich fürs Suchen und Sortieren interessant. Zum Vergleichen reicht Equals oder =.

-1 bedeutet, dass der erste String-Parameter lexikalisch kleiner ist als der zweite.
0 bedeutet, gleiche Strings
1 bedeutet, String 1 ist grösser als String 2.

Beispiel: "Anton" ist kleiner "Berta", Compare liefert Wert < 0.

Siehe auch IComparer-Interface. Das Interface vergleicht allgemein Objekte, nicht nur Strings.


Gruss
Pulpapex

Thema: Thread am Leben erhalten
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Bisschen Code wäre hilfreich gewesen.

Ich würde vermuten, dass dein Thread ohne Schleife ausgeführt wird. Ein Thread wird beendet, sobald die als ThreadStart oder ähnlich übergebene Methode zurückkehrt. Du brauchst eine Schleife, die solange läuft, bis der Client die Verbindung schliesst.

Den Verbindungsaufbau würde ich auch in den Thread verlagern. AcceptSocket oder AcceptTcpClient blockieren ansonsten genauso den Rest der Anwendung.


Gruss
Pulpapex

Thema: automatische berechnung einer rangfolge
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hi seth,

ich würde es wahrscheinlich so machen:

Alle Spieler-Objekte befinden sich in einer Liste, die nach dem Punktestand sortiert ist. Zum Sortieren kann man ArrayList.Sort verwenden. Als Parameter übergibt man einen selbst geschriebenen PunktestandComparer, der Spieler nach ihrer Punktestand-Eigenschaft vergleicht.

Der Index eines Spielers in der Liste entspricht dann seiner Platzierung.

Um einen Spieler mit einem gewissen Punktestand einzufügen, kann man ArrayList.BinarySearch zusammen mit dem PunktestandComparer verwenden. Als Ergebnis wird der Index zurückgegeben, an dem der Spieler eingefügt werden muss. Die Methode kann auch zur Ermittlung der Platzierung verwendet werden (oder jeder Spieler speichert seine Platzierung in einer Eigenschaft).


Gruss
Pulpapex

Thema: Werte speichern, warum ?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

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
Zitat
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

Thema: Threads
Am im Forum: Rund um die Programmierung

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

Thema: Konstruktoren in C# und der Umstieg Delphi -> C#
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

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

Thema: ins array schreiben
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

@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.

Thema: C# und eine Funktion wie "FindComponent" (Delphi)
Am im Forum: GUI: Windows-Forms

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

Thema: trotz Threading keine Performance?!
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

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

Thema: Zugriff auf DLL
Am im Forum: Rund um die Programmierung

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

Thema: Zeilen zählen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

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

Thema: Frage Zeichensatz XML, DataSet, HTML
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Umlaute sind in XML und HTML nicht erlaubt, die müssen durch Entities ersetzt werden. HTML definiert z.B. &auml; für ä oder &uuml; 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

Thema: Auswahlrechteck erstellen und transformieren
Am im Forum: GUI: Windows-Forms

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