C#-Witze

Um das Jahr ausklingen zu lassen, erlaube ich mir mal einen etwas weniger ernsten Blogbeitrag: Ich habe mich gefragt, ob es bereits Programmiererwitze gibt über C# und bin via Google auf die Suche danach gegangen. Resultat: Ich bin über eine ganze Menge guten Humor betreffend Informatik und Programmieren gestolpert, aber ganz spezifisch zu C# als Programmiersprache habe ich herzlich wenig gefunden.

Hier ein Witz zu C#, den es wohl auch analog zu anderen kontroversen Themen gibt, gefunden in diesem Forum-Thread und von mir etwas umformuliert:

Ein C#-Programmierer wird schwer krank und hat nicht mehr lange zu leben. Er geht zu einem Java-Programmierer und sagt zu ihm: “Ich brauche dringend deine Hilfe. Ich möchte bitte Java lernen.” Der Java-Programmierer erwidert erstaunt: “Du hast doch dein Leben lang aus Überzeugung nur C# verwendet! Warum willst du ausgerechnet jetzt Java lernen?” Der C#-Programmierer erklärt: “Lieber stirbt einer von denen als einer von uns.”

Im stets interessanten Blog Coding Horror bin ich auf meiner Humor-Suche über diesen Eintrag gestolpert mit dem witzigen Titel Compiler, It Hurts When I Do This, leider ohne einen eigentlichen C#-Witz, dafür mit einer lustigen Diskussion über Sinn und Unsinn von Identifiers in C#-Programmen, die so heissen wie reservierte Identifiers.

Ein weiteres Fundstück: ein C# Trivia Quiz, mit einem Teil 1 und einem Teil 2.

Das hier ist irgendwie selbst ein Witz, scheint aber tatsächlich passiert zu sein: Girl composes virus in C#.

Eine allgemeine Sammlung zum Thema Programmierer-Humor, die mir recht gut gefallen hat, findet man hier. Mein persönlicher Favorit daraus:

Why do programmers always mix up Halloween and Christmas? Because Oct 31 equals Dec 25.

Hier geht es darum, wie die Vertreter verschiedener Berufsgruppen (darunter natürlich auch Programmierer) in Afrika auf die Elefantenjagd gehen. Den Link habe ich aus demselben Forum-Thread wie obigen C#-Witz. Dort findet sich auch eine Aufforderung, man möge sich ausdenken, wie denn ein C#-Programmierer Elefanten jagen würde. Das ist gar nicht so einfach; hier trotzdem meine hoffentlich einigermassen witzigen Versuche dazu:

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Gar nicht. Microsoft erweitert das .NET-Framework so schnell, in der nächsten Version sind sicher auch Elefanten drin.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Er programmiert mit Hilfe von Generics, verschachtelten Klassen und Delegates ein dichtes Gestrüpp und wartet ruhig, bis sich ein Elefant darin verfängt.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Mit try … throw … catch natürlich.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Er blendet ihn per Reflection und nimmt ihn dann gefangen.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Mit C# natürlich. Die Programmiersprache ist so scharf, sie schneidet auch durch Elefantenhaut.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Gar nicht. Er klaut dem C++-Programmierer und dem Java-Programmierer je einen Elefanten.

Frage: Wie jagt ein C#-Programmierer Elefanten?
Antwort: Gar nicht. Er geht zum Mono-Projekt, dort gibt es Elefanten kostenlos.

Na denn, ein gutes neues Jahr allerseits!

Veröffentlicht in Keine Kategorie. Schlagwörter: . 2 Kommentare »

Die Performance von C#-Programmen

Die Programme der Megos sind heute im Prinzip sehr schnell, denn sie basieren auf C++-Code, arbeiten nicht exzessive mit dynamisch alloziertem Speicher und setzen direkt auf dem WIN32 API auf. Da stellt sich die Frage, wie es mit der Geschwindigkeit wohl aussehen wird, wenn wir dereinst diese Programme ablösen werden durch solche, die in C# geschrieben sind, wo schon der kleinste String ein volles Objekt ist und man in Form des .NET Frameworks eine ganze Menge Code zwischen sich und dem WIN32 API hat?

Um hier etwas Klarheit zu schaffen, habe ich mich heute erstmal schlau gemacht betreffend folgender vereinfachter Frage: Wenn man Code hat, der in etwa dasselbe tut, einmal in C++, und einmal in C#, ist dann der C#-Code per se langsamer, und wenn ja, um wieviel etwa?

Es hat sich herausgestellt, dass diese Frage nicht ganz einfach zu beantworten ist, denn Zeitmessungen haben so ihre Tücken. Ich habe z.B. in einem Forum Postings von jemandem gelesen, der versucht hat, die relative Geschwindigkeit dieser beiden Programmiersprachen (bzw. deren Implementationen auf Windows, wie sie heute sind) mit Hilfe kleiner Schleifen zu vergleichen, und zurückmeldete, die C++-Version sei 28000 Mal so schnell wie die C#-Version. Was war passiert? Der C++-Compiler war so schlau zu erkennen, dass eine zeitfressende Anweisung innerhalb der Schleife von der Schleife unabhängig war und hat sie als Optimierung aus der Schleife herausgenommen…

C#-Source-Code wird vom C#-Compiler übersetzt zu CIL (Common Intermediate Language), früher auch MSIL (Microsoft Intermediate Language) genannt, einem prozessorunabhängigen Bytecode, wie man z.B. in der Wikipedia hier nachlesen kann. Dieser wird dann üblicherweise bei der ersten Ausführung des Codes per JIT (Just in Time) Compiler quasi “fliegend” in direkte Prozessoranweisungen übersetzt und so schliesslich ausgeführt. Ob diese Übersetzung flüchtig ist oder dauerhaft abgespeichert wird, so dass später bei einer erneuten Programmausführung der Übersetzungsschritt gespart werden kann, hängt von verschiedenen Faktoren ab.

Kann es hier unter Umständen Geschwindigkeitsprobleme geben? Interpretiert man Bytecode statt direkt Prozessoranweisungen auszuführen, ist das schliesslich zwangsweise um einige Faktoren langsamer. Hatte nicht Java, das ebenfalls auf einem Bytecode basiert, vor Jahren zum Teil arge Geschwindigkeitsprobleme, bevor die HotSpot-JVM mit einem JIT-Compiler eingeführt wurde? Bei meinen Abklärungen heute erlebte ich diesbezüglich eine kleine Überraschung: Die Microsoft CLR scheint gar keinen Interpreter für CIL zu beinhalten, es wird nie interpretiert, sondern vor der Ausführung immer alles JIT-compiliert! (Details hierzu z.B. hier.) Also kann es hier keinen prinzipiellen Geschwindigkeitsverlust geben.

Das heisst nicht, dass keine CIL-Interpreter existieren: Mono hat zumindest in der Anfangsphase mit einem Interpreter gearbeitet, bevor ein JIT-Compiler zur Verfügung stand, und es gibt Dinge wie Dot Net Anywhere, einem CIL-Interpreter für Kleinstcomputer. Aber zumindest auf Windows lauert kein solcher und wartet auf Gelegenheiten, Performance zu vernichten.

Geschwindigkeitsunterschiede können sich auch durch Laufzeitprüfungen ergeben: C# überwacht normalerweise jeden einzelnen Array-Zugriff auf einen gültigen Index, während C++ das normalerweise nicht tut. In einem kleinen, synthetischen Testprogramm mit einer Schleife um Array-Zugriffe herum können sich hier schon einmal signifikante Unterschiede ergeben, aber ehrlich, in welchem Programm aus dem richtigen Leben wird schon so ein grosser Teil der Rechenzeit verbracht, und wer wollte allen Ernstes heute noch auf Laufzeitprüfungen verzichten?

Interessanterweise gibt es auch in C# Ansätze für Optimierungen, wenn man denn einmal ein Programmstück hat, das von Array-Zugriffen absolut dominiert wird. Im bereits erwähnten Thread finden sich folgende informative Code-Schnippsel:

Code A:

int[] arry = new int[20000];
for (int index = 0; index < 20000; ++index) {
  total += arry[index];
}

Code B:

int[] arry = new int[20000];
for (int index = 0; index < arry.Length; ++index) {
   total += arry[index];
}

Code C:

int[] arry = new int[20000];
foreach (int element in arry) {
  total += element;
}

Code B sei 20% schneller als Code A, weil durch die Verwendung von arry.Length der Compiler mitbekommt, dass er auf Bereichsprüfungen verzichten darf (wozu er wohl im Beispiel A nicht schlau genug ist), und Code C sei sogar 50% schneller als Code A, weil es offenbar foreach schafft, einen internen Index schneller durchzuzählen als das ein Programm explizit kann, und weil natürlich ebenfalls Bereichsprüfungen wegfallen.

Solche Tipps und noch viele mehr findet man offenbar in einem schlauen Buch namens Effective C#. Microsofts C# Programming Guide hat ebenfalls Informationen über Optimierungen, zu finden hier, und generelle Informationen darüber, was in Managed Code wie teuer ist, hier. Und wer einmal ganz tief in die CLR und ihre Objekt-Verwaltung hineinschauen möchte, um Ansätze für Optimierungen zu finden, kann das mit Hilfe der Informationen hier tun.

Zusammenfassend kann ich sagen, nirgends Hinweise darauf gefunden zu haben, dass man sich schon alleine durch die Verwendung von C# als Sprache generelle Performance-Probleme einhandelt, weil C# eben “langsam” ist. Schätzungen, die ich angetroffen habe, gehen davon aus, dass im allgemeinen C#-Code 80% bis 90% der Performance von C++-Code erreicht. Das dürfte zu verkraften sein!

Veröffentlicht in Keine Kategorie. Schlagwörter: , . 8 Kommentare »

Mehrfachvererbung

Manchmal wird man ziemlich unverhofft mit einem Problem konfrontiert, das man schon lange kannte, aber von dem man nicht ernsthaft erwartete, ihm jemals zu begegnen. So ging es mir mit der Mehrfachvererbung.

Ohne mich je genauer damit zu beschäftigen, war ich bisher der Meinung, es sei schon in Ordnung, dass viele Programmiersprachen Mehrfachvererbung nicht unterstützen, denn auf der einen Seite waren mir mögliche und vor allem sinnvolle Anwendungen nicht klar, aber auf der anderen Seite möglicher Ärger wie z.B. schwer verständliche Programme sehr wohl.

Umso mehr überrascht es mich, dass ich mir beim Design unseres neuen .NET-basierten Programmierwerkzeugs Triton jetzt genau diese Mehrfachvererbung wünsche, sie aber natürlich in C# nicht bekomme!

Worum geht es? Ich möchte die Funktionalität von Controls für Forms erweitern, notabene die von Standard-Controls wie TextBox, CheckBox, Button usw. Ich brauche z.B. Unterstützung für eine “schlaue” Validierung von Eingabewerten, wo ich zwischen “validiert in Bezug auf den aktuellen Wert des Controls selbst” und “validiert auch unter Berücksichtigung gegenseitiger Abhängigkeiten” unterscheiden möchte.

So entsteht der Bedarf, eine neue Angabe ValidationState bei den Controls unterzubringen, am liebsten gleich zusammen mit einigen Methoden, welche das Validieren unterstützen.

Natürlich steht es mir frei, von allen schätzungsweise etwa 10 System.Windows.Forms.Control-Klassen, die ich brauche, neue Klassen abzuleiten und bei allen diesen eine Property ValidationState einzuführen, aber so erhalte ich natürlich 10 verschiedene Klassen mit 10 völlig unabhängigen und inkompatiblen Properties.

Ideal wäre natürlich, die Basisklasse Control selbst um eine Property ValidationState plus zugehörigen Code erweitern zu können, aber zumindest mit C# 3.0 wäre der einzige Weg hierzu eine Modifikation des Framework-Source-Codes und eine Neukompilation, was für mich natürlich nicht in Frage kommt. Auch eine abgeschwächte Variante, bei der ich Control unverändert lasse, aber eine eigene Klasse SmartValidationControl oder so quasi in den Baum der Vererbung “einfügen” darf, hat dieselben nicht erfüllbaren technischen Voraussetzungen.

Und hier kommt jetzt die Mehrfachvererbung ins Spiel: 10 von diversen Controls abgeleitete Klassen wären in Ordnung, wenn sie ausser vom jeweiligen Control auch noch von einer zweiten Klasse SmartValidationControl ableiten dürften!

Was wäre mit 10 UserControl-Klassen mit einer gemeinsamen Basisklasse und mit dem jeweiligen eigentlichen Control als Kind? Dieser Ansatz ist natürlich möglich, artet aber aus in eine umfangreiche Fleissaufgabe, eine Menge Properties der Controls “durchzuschlaufen”, damit sie im Designer als Properties des Containers für Änderungen zur Verfügung stehen.

Schlussendlich bin ich beim folgendem Ansatz gelandet, den ich als das “geringste Übel” ansehe: Ich leite 10 Klassen von 10 verschiedenen Controls ab, gebe aber allen diesen Klassen ein bestimmtes Interface, das ich dann eben 10 Mal implementieren muss.

Bei meinen Abklärungen über Mehrfachvererbung per Google bin ich über ein paar Seiten gestolpert, die sich vielleicht lohnen weiterzugeben:

Hier erläutert jemand aus dem C#-Team von Microsoft, dass die CLR selbst offenbar einen Weg bietet für Mehrfachvererbung, damit zumindest im Prinzip die Möglichkeit besteht, .NET-basierte Compiler zu bauen für Sprachen, welche Mehrfachvererbung umfassen.

hier hat jemand Mehrfachvererbung in C# so sehr vermisst, dass er sich eine “Simulation” derselben ausgedacht hat, die recht trickreich mit Operatoren für implizite Typumwandlungen arbeitet. (Ich finde das Resultat insgesamt gesehen trotzdem ernüchternd.)

Und hier findet man schliesslich ein schon etwas älteres Interview mit dem “C# Compiler Program Manager” bei Microsoft, dem man die offizielle Haltung von Microsoft zum Thema entnehmen kann.

Anhand der vielen Treffer, die Anfragen nach multiple inheritance oder auch spezifisch c# multiple inheritance in Google produzieren, kann man sehen, dass es sich offenbar um eine Sache handelt, die immer wieder aufkommt. Es wäre interessant zu wissen, ob es keine elegante Lösung des Problems geben kann, weil das Universum eben ist wie es ist, oder ob einfach noch niemand die geniale Idee gehabt hat…

Veröffentlicht in Keine Kategorie. Schlagwörter: , , . 4 Kommentare »

Compiler Bootstrapping

Beim Lesen eines Berichts über die PDC 2008 in Los Angeles stiess ich auf ein Schnippsel Information, das ich ganz interessant fand: Für die nächste Version C# 4.0 sei unter anderem geplant, den C#-Compiler (bisher in C++) in C# neu zu schreiben.

Ich habe an der ETH Zürich studiert, wo vor allem dank Niklaus Wirth eine ganze Reihe von Sprachen und zugehörigen Compilern entstanden sind (darunter Pascal, Modula-2 und Oberon), und habe den Eindruck bekommen, dass dabei stets versucht worden ist, so schnell wie möglich zu einem “self-hosting compiler” zu kommen, d.h. zu einem Compiler, der in der Sprache geschrieben ist, die er compiliert.

Ich war deshalb überrascht zu lesen, dass in der Microsoft-Welt bis heute ein in C++ geschriebener Compiler allen C#-Code compiliert, und hatte sogar gewisse Zweifel, ob das wirklich stimmt – man soll ja nicht alles glauben, was im Internet steht…

Es ist nicht ganz einfach, eine klare Bestätigung zu finden für C++ als Implementations-Sprache des aktuellen C#-Compilers von Microsoft, aber dieser Thread hat mich schliesslich überzeugt.

Die Leute vom Mono-Projekt hatten es einfacher, weil sie den Microsoft-Compiler verwenden konnten, um ihren Compiler von Anfang an in C# zu schreiben, wie man z.B. hier nachlesen kann. Interessant ist, dass offenbar auch ein Microsoft-Mitarbeiter schon recht früh einen C#-Compiler in C# geschrieben hat (er berichtet über dieses Projekt hier), aber offenbar hat das die Compiler-”Hauptlinie” nicht beeinflusst.

Was hat die Konkurrenz so abgeliefert in Sachen “Compiler-Bootstrapping”? Bei Java hat es nach dem allerersten, noch in C geschriebenen Compiler offenbar auch etwa 3 Jahre gedauert, bis ein in Java selbst geschriebener Compiler zur Verfügung stand, wenn man diesem Artikel glauben darf.

Wie man in der Geschichte des ersten Pascal-Compilers für die CDC 6000 nachlesen kann, wurden sogar schon Compiler von Hand übersetzt, um zu einem self-hosting compiler zu kommen. Das waren noch Zeiten…

Veröffentlicht in 1. Schlagwörter: , . 1 Kommentar »

Framework Studio

Als die Megos vor einiger Zeit vor der wichtigen Frage stand, womit sie in Zukunft ihre Software entwickeln will, haben wir uns ein Produkt der deutschen Firma Framework Systems näher angeschaut, das sich Framework Studio nennt.

Ich war überrascht, was ich da zu sehen bekam, denn dieses System hat eine sehr interessante Architektur. Es läuft für mich quasi unter dem Motto “Erstaunlich, was man mit .NET alles machen kann”.

Beim Framework Studio handelt es sich um ein Software-Entwicklungssystem. Es entstehen Web-Applikationen, die man mit Hilfe einer Java-basierten Client-Komponente und einer C#/.NET-basierten Server-Komponente ausführt, zwischen denen via SOAP kommuniziert wird. Applikationen entstehen einerseits durch stark Tool-unterstützes Spezifizieren von Forms, Datenbank-Strukturen und Verarbeitungs-Logik, und andererseits durch Programmieren spezieller Logik direkt in C#.

Wie ein ausführlicher Artikel (Teil 1, Teil 2) erläutert, erlauben die Architektur des Systems und die Struktur der damit geschaffenen Applikationen eine ziemlich weit gehende Anpassbarkeit von Standard-Software.

Die Firma Nissen & Velten Software GmbH hat offenbar eine ERP-Lösung namens NVinity mit Hilfe des Framework Studio realisiert.

Trotz aller Faszination über das, was Framework Systems hier geleistet hat, haben wir auf den Einsatz von Framework Studio verzichtet. Ein Hauptgrund war unsere Entscheidung, nicht oder zumindest nicht ausschliesslich auf Web-Applikationen zu setzen, wie das hier nötig gewesen wäre. Jemandem, der hierin kein Problem sieht, kann ich aber durchaus empfehlen, sich die kostenlose Probeversion des Produkts mal anzuschauen. Selbst wenn es am Schluss nicht zu einem tatsächlichen Einsatz reicht, kann man als Software-Architekt mindestens die eine oder andere Idee mitnehmen und in seine “konventionelle” C#-Applikation einbauen.

Wenn dies nun etwas gar nach Werbung klingt: Nein, ist es nicht, aber ich kann eben meine Sympathie für eine Firma nicht verhehlen, die wie die Megos gegen Ende der 1980er-Jahre mit EMBASSY den Mut hat, Neues in einer Art zu versuchen, die man eher bei viel grösseren Firmen erwarten würde.

Etwas beunruhigend, dass offenbar NVinity immer noch die einzige vorzeigbare in Framework Studio realisierte Applikation ist. Da liegt noch viel Arbeit vor der Firma Framework Systems; Innovationen haben es eben oft schwer…

Veröffentlicht in 1. Schlagwörter: , . Kommentar schreiben »

Eine Art neues Grid für den Designer

Es ist im Designer des Visual Studio 2008 sehr viel einfacher geworden als früher etwa mit dem VB6-Designer, gutaussehende Forms zu produzieren, vor allem weil dank der Snaplines das Positionieren von Controls sehr viel einfacher geworden ist.

Dies ist auch gut so, wenn die Megos ihre Moneysoft-Applikationen, bisher entwickelt in einem einem eigenen System namens EMBASSY, in den nächsten Jahren in .NET neu schreiben will, denn wie man an folgendem, schon etwas älteren Screenshot sehen kann, wird es da oft Forms geben mit Dutzenden von Controls:

Valor Transaktionen

(Die vielen Controls in dieser Form sind nicht etwa schlechtes Design, sondern es gibt schlicht und einfach zu sogenannten Transaktionen in unserer Wertschriftenbuchhaltung Valor eine Menge Angaben, und die wollen alle erfasst werden. Für Kontrollen ist zudem ein schneller Überblick nötig, ohne dass man x Tabs wechseln muss.)

Als ich einmal eine solche Form testweise mit dem Visual-Studio-Designer nachbaute, merkte ich allerdings schnell, dass selbst die Unterstützung durch Snaplines noch nicht das ist, was ich eigentlich gerne hätte, um wirklich produktiv arbeiten zu können. Die Crux ist die: Forms, die praktisch nur aus vielen Labels, TextBoxes und GroupBoxes bestehen, sehen am besten aus (und die Controls haben am besten Platz), wenn man die Controls so positioniert und ihre Grössen so setzt, als würde man mit einem sehr speziellen Grid arbeiten – einem Grid, das mit einer “Zeilenhöhe” und einer “Durchschnittszeichenbreite” funktioniert.

Der Visual-Studio-Designer ist sehr modular aufgebaut und bietet eine Menge Möglichkeiten, Design-Prozesse zu beeinflussen, etwa mit Hilfe von ControlDesigner-Klassen, aber eine Möglichkeit, das Verhalten des Grids zu steuern oder zu übersteuern, scheint es nicht zu geben. Will man trotzdem mit einem speziellen Grid wie dem soeben beschriebenen arbeiten, muss man also zu einem Trick greifen.

Mein Trick ist der folgende: Controls haben eine protected virtual, also überdefinierbare Methode namens SetBoundsCore, die für das Setzen der Position und der Grösse eines Controls zuständig ist. Hier greife ich ein und runde Koordinaten auf mein Spezial-Grid, bevor ich sie an die Basis-Methode übergebe.

Das ist eine zwar drastische, aber einfache und effektive Methode, um x und y auf bestimmte Werte zu zwingen. Nichts und niemand im ganzen System kommt um die von mir etablierte Rundung der Koordinaten herum, auch der Designer nicht. Der Effekt im Designer ist der, dass man zwar ein solches Control nach wie vor mit der Maus frei herumziehen kann, aber sobald man es “absetzt”, kommt die geänderte SetBoundsCore-Methode zum Zug, und das Control hüpft sozusagen von sich aus auf die “richtige” Position gemäss Grid. Das ist natürlich ungewohnt und am Anfang auch etwas gewöhnungsbedürftig, fühlte sich aber für mich schon nach kurzer Zeit sehr angenehm an.

Folgendes kleine Code-Fragment zeigt ein Label-Control, welches man nur gemäss einem Grid positionieren kann, dessen Zellen 30 Pixel breit und 15 Pixel hoch sind (vielleicht nicht unbedingt nützlich, zeigt aber den Effekt im Designer sehr schön):

  public class GriddedLabel : Label {
    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
      x = (x / 30) * 30;
      y = (y / 15) * 15;
      base.SetBoundsCore(x, y, width, height, specified);
    }
  }

ReadOnlyCollection

Jeder, der eine halbwegs umfangreiche Klassen-Sammlung in C# designen muss, hat gute Chancen, auf folgende grundlegende Design-Frage zu stossen: Eine Klasse soll eine List enthalten, die zwar gegen aussen sichtbar ist, die man aber nicht direkt verändern darf – sämtliche Änderungen sollen quasi indirekt mit Hilfe von Methoden der Klasse erfolgen. Für eine solche Anforderung kann es viele denkbare Gründe geben; schon nur, wenn man die Anzahl Änderungen an der List zählen möchte, sollte es besser nicht möglich sein, dass sich jemand an der Zählung vorbeimogelt, indem er sich die Liste geben lässt und sie dann selbst verändert.

Ein kleines synthetisches Codebeispiel hierzu:

namespace ReadOnly {
  class Container {

    private List<int> numbers;
    public List<int> Numbers {
      get { return numbers; }
    }

    public void AddNumber(int n) {
      numbers.Add(n);
    }

    public Container() {
      numbers = new List<int>();
    }
  }

  class Program {
    static void Main(string[] args) {
      Container c=new Container();
      c.AddNumber(5);     // soll nur so funktionieren
      c.Numbers.Add(5);   // soll verboten sein
    }
  }
}

Mein erster Gedanke war, dass es in C# vielleicht ein Äquivalent zu C++ const gibt und man damit etwas machen kann. Eine Abklärung ergab, dass die CLR zwar eine gewisse Unterstützung bietet in dieser Richtung (für Managed C++), diese aber in C# nicht zur Verfügung steht.

Dann stiess ich auf die Property IsReadOnly, welche im Interface IList enthalten ist. Das sieht zwar auf den ersten Blick hoffnungsvoll aus, aber die Anwesenheit dieser Property im Interface heisst noch lange nicht, dass man im Falle einer “templated class” etwas damit machen kann. Ich habe auf jeden Fall keinen Weg gefunden, im konkreten Falle einer List<int> deren Property IsReadOnly irgendwie zu überdefinieren, und selbst wenn dies gelänge, würden sich wohl Methoden wie Add der Template-basierten Klasse überhaupt nicht dafür interessieren.

Schliesslich förderte meine Suche die Klasse ReadOnlyCollection zu Tage, welche man wie folgt auf das Problem ansetzen kann:

namespace ReadOnly {
  class Container {

    private List<int> numbers;
    public ReadOnlyCollection<int> Numbers {
      get { return numbers.AsReadOnly(); }
    }

    public void AddNumber(int n) {
      numbers.Add(n);
    }

    public Container() {
      numbers = new List<int>();
    }
  }

  class Program {
    static void Main(string[] args) {
      Container c = new Container();
      c.AddNumber(5);     // funktioniert nur so
      c.Numbers.Add(5);   // compiliert nicht, 'ReadOnlyCollection.Add' gibt es nicht
    }
  }
}

Etwas unbefriedigend an dieser Lösung ist, dass mit Hilfe der Methode AsReadOnly ein neues Objekt erzeugt werden muss.

In irgendeinem Forum habe ich dann folgende Lösungs-Variante gefunden, welche ohne ein neues Objekt auskommt:

namespace ReadOnly {
  class Container {

    private List<int> numbers;
    public IEnumerable<int> Numbers {
      get { return numbers; }
    }

    public void AddNumber(int n) {
      numbers.Add(n);
    }

    public Container() {
      numbers = new List<int>();
    }
  }

  class Program {
    static void Main(string[] args) {
      Container c = new Container();
      c.AddNumber(5);     // funktioniert nur so
      c.Numbers.Add(5);   // compiliert nicht, 'IEnumerable.Add' gibt es nicht
    }
  }
}

Eine List<int> implementiert natürlich selbst bereits das Interface IEnumerable, so dass die Sache rein zur Compilierzeit stattfindet und die Property Number technisch gesehen gleich die Liste selbst zurückgibt. Unschön ist allerdings, dass man mit einem IEnumerable-Objekt nichts weiter machen kann als per foreach die Elemente durchgehen; noch nicht einmal die Anzahl Elemente kann man direkt abfragen.

Nach einigem Abwägen habe ich beschlossen, für die Megos-eigene Klassen-Bibliothek Triton, die gerade entsteht, das Problem zu ignorieren und keine technische Vorkehrungen zu treffen, um mit Hilfe einer der geschilderten Methoden Veränderungen an solchen Listen zu verhindern. Wir sind wenige, erfahrene, disziplinierte Programmierer, die keine Mühe haben mit dem Befolgen von Konventionen wie “Verändere keine Listen-Properties direkt”.

Natürlich sähe das anders aus, wenn man z.B. eine kommerziell vertriebene Klassen-Bibliothek für den Gebrauch durch viele andere Programmierer bauen müsste. Aber auch da gäbe es vielleicht die Möglichkeit, die direkten Veränderungen selbst nicht zu verunmöglichen, sie aber dennoch zu entdecken und mit einer Exception zu beantworten, indem man einerseits die Anzahl Aufrufe von AddNumber zählt und andererseits an “strategischen” Orten im Code die Anzahl Elemente der Liste gegen diesen Zähler prüft.

Veröffentlicht in Keine Kategorie. Schlagwörter: , . Kommentar schreiben »

Vorkonfigurierte Controls

Ich vermute, dass ausser mir eine ganze Reihe von .NET-Programmieren auch schon in folgender Situation waren: Man muss eine neue Form mit einer ganzen Reihe von Controls definieren im Designer, und für viele der Controls stehen eine Anzahl von Eigenschaften eigentlich schon von Beginn weg fest, und mit der Zeit wünscht man sich, der Designer würde – irgendwie! – diese Eigenschaften gleich beim Erzeugen der Objekte von selbst richtig setzen, so dass man das nicht für x Controls wieder und wieder von Hand selbst tun muss.

Ein Beispiel: Eine Firma arbeitet gewissen Normen punkto Buttons. Sie müssen alle dieselbe, festgelegte Grösse haben, und der Name sei abzuleiten vom Text des Buttons. Wie schön wäre es doch, wenn man dem Designer eine Funktion Erzeuge Standard-Button beibringen könnte, die nach Eingabe des Button-Textes den Button gleich so erzeugt?

Hier würde natürlich ein User Control Standard-Button auch helfen, aber wenn das Szenario nur etwas vielfältiger wird, wie im folgenden Beispiel, ist das kein geeignetes Mittel mehr:

Man portiert eine alte Applikation auf .NET und beginnt mit der Form nicht bei Null, sondern hat im Prinzip die Liste der Controls für die Form schon, als Tabelle in einer Textdatei, mit Namen, Typen und Längen, vom “alten” Entwicklungs-System her. Es wäre doch schön, diese Tabelle irgendwie im Designer einlesen zu können und für jedes “alte” Control ein entsprechendes .NET-Control zu erzeugen.

Wie viele Dinge im .NET-Framework geht ein solchermassen Code-gesteuertes Erzeugen von Controls im Designer ziemlich einfach, wenn man den “Kniff” kennt:

Man schafft sich zuerst die Möglichkeit, eigenen Code im Designer-Kontext laufen zu lassen, z.B. indem man einen System.Windows.Forms.Design.ControlDesigner samt DesignerActionList implementiert, und kann anschliessend neue Controls mit Hilfe des aktiven IDesignerHost-Objekts ganz einfach erzeugen:

   IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
   Button b = (Button)designerHost.CreateComponent(typeof(Button), buttonName);
Veröffentlicht in Keine Kategorie. Schlagwörter: , . Kommentar schreiben »

Zugriff auf unterschiedliche Datenbank-Server

Vielleicht ist das, worüber ich hier schreibe, für Sie bereits ein alter Hut, weil es schon im Framework 2.0 eingeführt wurde, aber vielleicht kennen Sie es ja noch nicht, weil Microsoft die Sache nicht an die grosse Glocke hängt:

In unserem Entwicklungswerkzeug EMBASSY waren wir es gewohnt, mit Hilfe von ODBC generisch auf verschiedene Datenbank-Server zuzugreifen, konkret vor allem auf Microsoft SQL Server und Oracle. Das ist ja zum grossen Teil überhaupt der Witz einer Treiber-artigen Schnittstelle wie ODBC, dass Dinge abstrahiert werden und so eine weitgehend generische Programmierung möglich wird.

Umso überraschter waren wir damals bei einem Blick auf das .NET Framework 1.1, dass eine solche Abstraktions-Ebene nicht in Sicht war. Gemäss Microsoft das bevorzugte Mittel, um auf Datenbank-Server zuzugreifen: auf den jeweiligen Server zugeschnittene, spezifische eigene Klassen, also Klassen wie SqlConnection und OracleConnection, SqlCommand und OracleCommand, usw.

Auf der einen Seite sind solche massgeschneiderten Klassen natürlich hübsch, aber auf der anderen Seite eben ein Hindernis beim Versuch, ein Programm zu schreiben, dass via einfache Konfigurations-Angabe von einem Server-Typ auf einen anderen wechseln kann. Und ja, auch klar, dass Microsoft nicht unbedingt möchte, dass alle Programme ganz einfach vom hauseigenen SQL Server auf das Konkurrenz-Produkt Oracle umschaltbar sind, aber dass die Hürde dann gleich so gross herauskommt?

Glücklicherweise hatte Microsoft bereits bei der Version 2.0 des Framework ein Einsehen: Das Zauberwort heisst DbProviderFactory. Eine DbProviderFactory offeriert Methoden, wie man auf generische Weise zu Connection-Objekten, Command-Objekten usw. kommt.

Die Methode GetFactory der statischen Klasse DbProviderFactories dient dazu, eine DbProviderFactory zu beschaffen, wenn man den Namen des Providers kennt, also z.B. System.Data.OracleClient.

Natürlich geht es bei jedem nicht-trivialen Programm nicht komplett ohne das Wissen, auf welchem Typ Server man gerade arbeitet, denn es bleiben Unterschiede bei den unterstützten Datentypen, bei einigen SQL-Anweisungen wie z.B. CREATE TABLE, und bei den auftretenden Exceptions, um die man sich explizite kümmern muss, aber über weite Strecken wird der Code dank den “Factories” tatsächlich frei von Fallunterscheidungen.

Veröffentlicht in Keine Kategorie. Schlagwörter: , . Kommentar schreiben »

Programmiersprachen-Popularität

Wenn man wie die Megos im Moment von einer Programmiersprache (C++) auf eine andere (C#) wechselt als Basis für seine Applikationen, wäre es ab und zu ganz verlockend, etwas in Richtung einer Bestätigung zu bekommen, dass man tatsächlich auf das “richtige” Pferd setzt.

Ich habe kürzlich einen Artikel gelesen, wo eine Statistik erwähnt wurde, welche die Beliebtheit von Programmiersprachen messen möchte, und bin der Sache nachgegangen, eben um zu sehen, wie es gemäss dieser Statistik um C# steht.

Es handelt sich um den sogenannten TIOBE Programming Community Index. Er wird offenbar ermittelt, indem in den populärsten Suchmaschinen nach dem Begriff <Programmiersprache> programming gesucht wird, konkret bei C# also nach C# programming und einer Reihe naher verwandter Suchbegriffe wie C sharp programming.

Die solchermassen 50 beliebtesten Programmiersprachen d.h. alle Hits für die 50 mit den meistens Hits bilden die 100%.

Man kann sich natürlich trefflich über die Genauigkeit von Resultaten streiten, die auf diese Weise zu ermitteln sind. Man könnte über ganz verschiedene Dinge meckern, z.B. die Beschränkung auf englische Suchbegriffe oder die Tatsache, dass eine Programmiersprache im Zentrum eines “Hype” zwar auf eine Menge Hits kommt, aber dass deswegen noch lange nicht viel damit programmiert wird. Darüber hinaus dürften ältere Sprachen einen Bonus bekommen, weil einfach länger Zeit war, im Web etwas über sie zu veröffentlichen.

Aber immerhin, lustig ist so eine Statistik natürlich trotzdem: Im Juni 2008 steht C# an 8. Stelle, mit einem Anteil von knapp über 4%.

Nach meiner Beurteilung ist das ganz ordentlich für eine Sprache, die so jung ist. Wie man unter der Überschrift Long time trends auf der erwähnten Seite in einem Chart sehen kann, geht es zudem aufwärts mit C# – nicht spektakulär, aber stetig.

Ich schlage diese Statistik mal hinzu zu den guten Fortschritten beim bisherigen Arbeiten mit C# in der Megos und zur Tatsache, dass eine ganze Reihe anderer, vergleichbarer Schweizer Software-Häuser ihre “Next Generation”-Software mit .NET erstellt hat.

Veröffentlicht in Keine Kategorie. Schlagwörter: . Kommentar schreiben »
Follow

Bekomme jeden neuen Artikel in deinen Posteingang.