Home
Themen
Angebote
Downloads
News & Blogs
    ZfS News
    .NET & C#
    ASP.NET & Sharepoint
    ADO.NET & Datenbanken
    Windows
    Lehre
    Blogs nach Personen
Informatiklandkarte
DBWorld Map
.NET Glossar
Wir über uns
Kontakt
Newsletter

News

Thursday, August 31, 2006

Bilder vom Länderabend NRW  #

Das ZfS Aachen war gestern zu Gast auf dem Länderabend der Microsoft Deutschland GmbH im Düsseldorfer Landtag. Zahlreiche prominente Gäste aus der Landespolitik haben sich über das breite Angebotsspektrum unseres Zentrums informiert. Jürgen Gallmann, Chef vom Microsoft Deutschland, ging in seiner Wilkommensansprache ausführlich auf das Aachener ZfS und dessen Leistungen für den Mittelstand sowie das Kursangebot für Lehrerinnen und Lehrer ein. In vielen persönlichen Gesprächen konnten wir dann ausführlich von unseren Aktivitäten berichten.

Zu Gast waren unter anderem Landtagspräsidentin Regina van Dinther, Finanzminister Helmut Linssen, Minster Armin Laschet, Axel Horstmann, Detlev Samland, Angie Gifford, Andrea Milz, Staatssekretär Jens Baganz, Thomas Mickeleit, Mike Cosse, Achim Bahnen, Michael Vesper.

Bilder von der Veranstaltung finden Sie in unserem Fotoalbum!

Monday, August 28, 2006

BackgroundWorker zum Aktualisieren von GUI-Elementen  #

In einem früheren Blog-Eintrag haben wir gezeigt, wie man durch die Verwendung von Delegates und Threads GUI-Komponenten mit Daten aus parallel laufenden Arbeitsprozessen aktualisieren kann. In .NET 2.0 gibt es dafür ein vorgefertiges Pattern, dass die Lösung für dieses Problem etwas leichter macht. Die notwendige Klasse heißt BackgroundWorker und befindet sich im Namespace System.ComponentModel.

Die Verwendung eines EventHandlers (oder eines Delegates) ist bei einem Programm mit mehreren Threads und grafischer Benutzeroberfläche deswegen notwendig, weil Aktualisierungen des GUIs nur in dem Thread durchgeführt werden können, der auch die GUI-Komponenten konstruiert hat (normalerweise der Haupt-Thread eines Programms). Das klassische Anwendungsszenario dafür ist eine ProgressBar, in der der aktuelle Stand einer langwierigen Operation gezeigt werden soll, die in einem separaten Thread abläuft. Die BackgroundWorker-Klasse stellt die notwendigen Elemente dafür bereit. Die folgenden vier Zeilen definieren ein neues Objekt dieser Klasse, registrieren die Event-Handler und starten den Arbeitsprozess.

 BackgroundWorker bw = new BackgroundWorker();
 bw.DoWork += new DoWorkEventHandler(bw_DoWork);
 bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
 bw.RunWorkerAsync();

In der BackgroundWorker-Klasse sind u.a. zwei Events definiert:
  • DoWork: Hier werden die Funktionen registriert, die die eigentliche Arbeit ausführen, z.B. ein längerer Download, Lesen der Daten von einem SerialPort, usw. Das Delegate hat zwei Parameter: ein Sender vom Typ Object (dies ist das BackgroundWorker-Objekt) und DoWorkEventArgs, über die man weitere Parameter an die Arbeitsfunktion senden kann.
  • ProgressChanged: Diese Event-Handler werden aufgerufen, wenn der Arbeitsprozess eine Änderung gemeldet hat. Dafür muss der Arbeitsprozess die Methode ReportProgress des BackgroundWorker-Objekts aufrufen. Im Event-Handler wird dann die GUI-Elemente aktualisiert.
Die Methode RunWorkerAsync() startet den Arbeitsprozess des BackgroundWorkers. Um das Beispiel zu vervollständigen müssen noch die Methoden bw_DoWork und bw_ProgressChanged definiert werden:

 void bw_DoWork(object sender, DoWorkEventArgs e) {
   BackgroundWorker worker = sender as BackgroundWorker;
   while(...) {
     // do the work ...
     // notify GUI about change
     backgroundWorker.WorkerReportsProgress = true;
     backgroundWorker.ReportProgress(percentage,userState); 
   }
 }

 void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) {
   progressBar.Value=e.ProgressPercentage;
   // Weitere Infos über e.UserState
 }

In der Methode bw_DoWork ist der Aufruf von ReportProgress entscheidend, hier wird der GUI-Thread über eine Änderung des Status informiert, die dann letztlich in bw_ProgressChanged durchgeführt wird. Standardmäßig kann man bei ReportProgress einen Integer-Wert angeben, der den Fortschritt des Prozesses angibt. Wenn man komplexere Informationen an das GUI weiterleiten will, kann man dies über den UserState tun, der ein beliebiges Objekt sein kann. Der UserState kann über eine Property der ProgressChangedEventArgs im Event-Handler abgefragt werden.

Signierung eines Assemblies ohne Visual Studio  #

Mit dem Beitrag vom 22.08. „Signierung eines Assemblies mit dem Visual Studio 2005“ wurde gezeigt, wie Assemblies mit dem Visual Studio 2005 signiert werden können. Die Signierung von Assemblies ist eine notwendige Voraussetzung, um diese als Shared Assemblies in den Global Assembly Cache (GAC) installieren zu können, damit diese systemweit von allen .NET-Applikationen eingebunden werden können.

Selbstverständlich können Assemblies aber auch ohne VS 2005 signiert werden. Dazu sind die folgenden zwei Schritte notwendig:

 

  1. Erstellung eines Schlüsselpaares (öffentlicher und privater Schlüssel)
  2. Signierung des Assemblies unter Angabe der Schlüssel-Datei

 1. Erstellung eines Schlüsselpaares

 

Mit dem SDK wird die Anwendung Strong Name Utility mitgeliefert, die einen öffentlichen und einen privaten Schlüssel erstellt und in einer Datei abspeichert. Zur Generierung der beiden Schlüssel mit dieser Anwendung geben Sie als Kommandozeile den folgenden Befehl ein:

sn.exe –k keys.snk

Dies erzeugt im aktuellen Verzeichnis eine Datei keys.snk, die die Schlüssel enthält. Kopieren Sie diese Datei in Ihr Projekt-Stammverzeichnis.

Hinweis: Durch die Kommandozeile sn.exe –p keys.snk pubkey.snk erhalten Sie in der Datei keys.snk das Schlüsselpaar, während die Datei pubkey.snk lediglich den öffentlichen Schlüssel enthält. Dies kann hilfreich sein, falls Sie den öffentlichen Schlüssel einmal separat aus der Hand geben möchten.

 

2. Signieren des Assemblies

Über eine Attributangabe im Quellcode kann das Assembly nun signiert werden:

 

using System;

using System.Reflection;

 

[assembly:AssemblyKeyFile("keys.snk")] //<your keyFile-Name>

 

 

namespace ClassLibrary1

{

    public class MyFirstSharedAssembly

    {

      //some code here

    }

}

Das Attribut AssemblyKeyFile benötigt als Parameter den Pfad zur Datei, in der das Schlüsselpaar gespeichert wurde.

Hinweis: Weitere Informationen zur Erstellung, Installation und Nutzung von Shared Assemblies finden Sie auch in dem HowTo-Dokument „Erstellung und Installation eines Shared Assemblies“. Dieses Dokument ist nur für angemeldete Nutzer verfügbar. Nutzen Sie unser Anmeldeformular, um  sich kostenlos anzumelden. Sie haben dann uneingeschränkten Zugriff auf alle Dokumente und Beispielanwendungen aus unserem Downloadbereich!

 

Friday, August 25, 2006

C#-FAQ: Bestimmung eines Initialwerts zur iterativen Berechnung von Maximal- und Minimalwerten  #

Bei der Programmierung stellt die iterative Berechnung von Minimal- oder Maximalwerten einer Liste, die in einer Schleife prozessiert wird, einen typischen Anwendungsfall dar. Dabei wird häufig mit folgender if-Abfrage entschieden, ob ein aktuell prozessierter Listenwert größer/kleiner als der gegenwärtige Max/Min-Wert ist:

 

if (actValue > maxValue) maxValue = actValue; //bei Maximalwert-Bestimmung

if (actValue < minValue) minValue = actValue; //bei Minimalwert-Bestimmung

 

Nun stellt sich die Frage, mit welchem Wert man maxValue /minValue idealerweise beim Start der Schleife initialisiert? Das Problem dabei ist, dass bei zu großer (bei einer Minimalwert-Berechnung) oder zu kleiner (bei einer Maximalwert-Berechnung) Initialisierung ein falscher Wert bestimmt wird.

Schaut man sich z.B. die Ermittlung eines maximalen Werts aus einer Liste von Integer-Werten an, muss man maxValue so initialisieren, dass mind. ein Wert der Liste größer ist (nämlich mindestens der maximale Wert der Liste). Analog gestaltet sich das Problem bei der Berechnung eines minimalen Werts. Im Rahmen der Maximalwert-Bestimmung muss man demnach den kleinst möglichen Zahlenwert als Initialwert wählen.

 

Die Lösung dieser Aufgabe ist denkbar simpel: man nutzt die Konstante MaxValue bzw. MinValue der Integer-Datentypen. Möchte man z.B. den maximalen Wert einer Liste mit Int32-Werten bestimmen, initialisiert man maxValue mit

 

int maxValue = Int32.MinValue;

 

So muss mindestens ein Wert in der Liste exisitieren, der größer ist als der initiale maxValue-Wert (es sei denn, alle Werte der Liste entsprechen dem Initialwert, dann ist der Maximalwert dennoch korrekt bestimmt). Analog kann man z.B. auch die Kontante Int64.MinValue oder Double.MinValue  für einen entsprechenden Anwendungsfall nutzen. Für die Berechnung des Minimalwerts einer Int32-Liste gilt analog:

 

int minValue = Int32.MaxValue;

Thursday, August 24, 2006

Windows-Programme über Dienst starten  #

Normalerweise haben Programme, die auf einem Server laufen, keine direkte grafische Benutzerschnittstelle und brauchen demnach auch weniger Ressourcen. Diese Anwendungen werden üblicherweise als Konsolen-Anwendungen erstellt. Bei einem unserer Kunden gibt es aber den Fall, dass auf dem Server Windows-Programme gestartet werden müssen, die das Backend einer Webanwendung sind. Für jeden Benutzer muss es eine eigene Instanz dieser Anwendung geben, in diesem Fall sollten mehrere hundert Benutzer gleichzeitig auf den Server zugreifen können. Eine Windows-Anwendung ist deswegen notwendig, da auf dem Server auch PDF-Dateien über die Druckfunktion erstellt werden sollen, und diese Funktion ist nur in "richtigen" Windows-Programmen verfügbar.

Wo liegt nun das Problem? Dienste und auch Programme, die durch Dienste gestartet werden, laufen in einem speziellen Kontext des Windows-Betriebssystems ab, in dem weniger Ressourcen zur Verfügung stehen, als im normalen Kontext eines angemeldeten Benutzers. Dieser Kontext setzt sich aus einem WindowStation-Objekt und einem Desktop-Objekt zusammen. Aufgrund der eingeschränkten Ressourcen konnten bei unserem Kunden nur ca. 60 Anwendungen gestartet werden, obwohl mehr als 300 erforderlich waren. Prinzipiell gibt es zwei Arten von WindowStations:
  • Interactive: für "interaktive" Desktops wie der Desktop eines Benutzer, Logon oder Screen-Saver
  • Noninteractive: für Dienste und Anwendungen, die durch Dienste gestartet werden
Über einen Eintrag in der Registry wird gesteuert, wie viele Ressourcen einem Desktop zur Verfügung stehen. Dieser Eintrag ist
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows
und hat einen länglichen Eintrag zum Start des CSRSS-Prozess. Der wesentliche Teil ist der SharedSection-Parameter, der normalerweise so aussieht: SharedSection=1024,3072,512. Diese drei Werte geben an, wie viele Ressourcen (in KB) den Heaps der einzelnen Desktops zur Verfügung stehen. Im Heap eines Desktops werden die Referenzen zu allen GUI-Objekten wie Fenster, Menus usw. gespeichert. Der erste Wert ist die Größe eines "Shared Heap", der gemeinsam von allen Desktops benutzt wird. Der zweite Wert ist die Größe des Heaps für interaktive Desktops. In der Regel müssen diese beiden Werte nicht verändert werden. Interessant für uns ist der dritte Wert, der die Größe des Heaps für nicht-interkaktive Desktops angibt. Durch Vergrößern dieses Werts konnte das Problem unseres Kunden gelöst werden und es kann die erforderliche Zahl von Benutzern parallel auf die Anwendung zugreifen.

Weitere Informationen zum SharedSection-Parameter finden Sie in diesem Artikel der MSDN-KB.

Wednesday, August 23, 2006

Neues HowTo-Dokument zur Erzeugung, Installation und Verwendung von Shared Assemblies zum Download  #

Ab sofort ist das HowTo-Dokument „Erstellung und Installation eines Shared Assemblies“ im Downloadbereich verfügbar.

Dieses Dokument beschreibt, wie Shared Assemblies (auch als Public Assemblies bekannt) erstellt, in den Global Assembly Cache (GAC) installiert und anschließend von anderen Assemblies referenziert werden können.

 

Dieses Dokument ist nur für angemeldete Nutzer verfügbar. Nutzen Sie unser Anmeldeformular, um  sich kostenlos anzumelden. Sie haben damit uneingeschränkten Zugriff auf alle Dokumente und Beispielanwendungen aus unserem Downloadbereich!

 

Tuesday, August 22, 2006

Signierung eines Assemblies mit dem Visual Studio 2005  #

Zur Signierung eines Assemblies mit dem Visual Studio 2005 sind die folgenden zwei Schritte notwendig:

 

  1. Erstellung eines Schlüsselpaares (öffentlicher und privater Schlüssel)
  2. Signierung des Assemblies unter Angabe der Schlüssel-Datei

 1. Erstellung eines Schlüsselpaares

 

Um mit dem VS 2005 ein Schlüsselpaar zu erstellen, öffnen Sie das Projekt-Eigenschaftsfenster über die Menüfolge „Project“ -> „<Your ProjectName> Properties“. Es öffnet sich das Eigenschaftsfenster des aktuellen Projekts. Wechseln Sie zur Registerkarte „Signing“ und aktivieren Sie die Checkbox „Sign the assembly“. Wählen Sie nun den Eintrag „<New>“ aus der Auswahlbox. Es öffnet sich ein Dialog-Fenster zur Eingabe eines geeigneten Dateinamens, in dem das Schlüsselpaar gespeichert werden soll. Optional können Sie Ihr Schlüsselpaar mit Login und Passwort sichern. Bestätigen Sie Ihre Eingaben mit dem Schaltknopf „OK“. Ihr Schlüsselpaar wird nun generiert und in der angegebenen Datei gespeichert.

 

2. Signierung des Assemblies

 

Um mit dem VS 2005 ein Assembly unter Angabe einer Schlüsseldatei zu signieren, öffnen Sie das Projekt-Eigenschaftsfenster wie unter 1. beschrieben. Wechseln Sie zur Registerkarte „Signing“ und aktivieren Sie die Checkbox „Sign the assembly“.

Wählen Sie nun aus der Auswahlbox den Punkt „<Browse>“ (oder alternativ die Schlüsseldatei, falls Sie den ersten Schritt ausgeführt haben und diese damit direkt gelistet sein sollte) und wählen Sie Ihre Schlüsseldatei über den Dateiauswahl-Dialog.

 

Beim nächsten Kompiliervorgang wird das Assembly automatisch mit dem spezifizierten Schlüssel signiert. Die digitale Signatur wird in das Manifest des Assemblies eingetragen.  Die Signierung des Assemblies ist eine notwendige Voraussetzung, um als Shared Assembly in den Global Assembly Cache (GAC) installiert zu werden. Daneben haben Shared Assemblies u.a. die folgenden Vorteile:

 

-          aufgrund der Signierung und des öffentlichen Schlüssels ist eine Authentifizierung vor der Ausführung durch die CLR möglich

-          durch die Angabe einer Versionsnummer kann das Vorhandensein einer exakt definierten Assembly-Version vor der Ausführung erzwungen werden.

-          durch die Verwendung der Versionsnummer als Bestandteil der Assembly-Identität können im GAC gleichzeitig mehrere Versionen desgleichen Assemblies installiert und von anderen Anwendungen genutzt werden

 

Hinweis: alle Angaben zu Visual Studio 2005 beziehen sich auf die englischsprachige Version 8.0.50727.42

 

ZfS Aachen auf dem Länderabend NRW  #

Am 30. August 2006 präsentiert Microsoft Deutschland sein wirtschaftliches und gesellschaftliches Engagement bei einem Länderabend in der Villa Horion in Düsseldorf. Das ZfS Aachen ist natürlich auch dabei! Neben grundlegenden Informationen zu unserem umfangreichen Angebot stellen wir insbesondere unser Kursprogramm für Lehrerinnen und Lehrer vor.

Monday, August 21, 2006

Eigene Attribute definieren  #

Wie im Blog-Eintrag vom 14.08.2006 erwähnt, kann man eigene Attribute definieren.

Zuerst erstellt man eine Klasse die von System.Attribute abgeleitet ist. Es ist eine gängige Praxis, eigene Attribut-Klassen als sealed zu markieren. Alle Attributklassen haben als Suffix "Attribute".

public sealed class UserDescriptionAttribute : System.Attribute {

private String _description;

public UserDescriptionAttribute(String description) {
_description = description;
}
public UserDescriptionAttribute() { }

public String description() {
get { return _description; }
set {_description = value; }
}

}

Beim Anwenden des neuen Attributes hat man die Möglichkeit, den kompletten Namen anzugeben (inklusive Suffix "Attribute") oder die Kurzform.

[UserDescriptionAttribute("Alle Schueler gehen in eine Klasse")]
public class Schueler{

// ...

}

[UserDescription("Alle Lehrer unterrichten eine oder mehrere Klassen")]
public class Lehrer {

// ...

}

Man kann die Verwendung von eigenen Attributen einschränken. Dazu gibt es das Attribut [AttributeUsage] und man kann folgende Werte benutzen:

public enum AttributeTargets {

All, Assembly, Class, Constructor, Delegate, Enum, Event, Field,
Interface, Method, Module, Parameter, Property, ReturnValue, Struct

}

Wenn wir definieren möchten, dass unser eigenes Attribut nur in Classen und Assemblies benutzt werden soll, sieht die Klasse folgendermassen aus:

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class)]
public sealed class UserDescriptionAttribute : System.Attribute {

private String _description;

public UserDescriptionAttribute(String description) {
_description = description;
}
public UserDescriptionAttribute() { }

public String description() {
get { return _description; }
set {_description = value; }
}

}

Es empfiehlt sich, die Einschränkung für die Benutzung der eigenen Attribute immer mit anzugeben.

Friday, August 18, 2006

Komponentenbasierte Architektur: benutzerdefinierte Metadaten in C#  #

Komponentenbasierte Softwarearchitekturen basieren auf dem Prinzip, Applikationen aus mehreren, a priori autonomen (kontextfreien) Einheiten zu komponieren, die untereinander Informationen/Daten austauschen und definierte Teilaufgaben erledigen.

Mitunter kommt eine Kooperation dieser Einzel-Komponenten ad hoc zustande, d.h. die Ermittlung einer für ein bestimmtes Arbeitspaket geeigneten Komponente und anschließende Aufgabenverteilung wird erst zur Laufzeit entschieden. Damit eine solche Arbeitsorganisation effektiv gestaltet werden kann, benötigen die einzelnen Komponenten gegenseitige Informationen (z.B. welche Funktionalitäten von einzelnen Komponenten zur Verfügung gestellt werden, wie Schnittstellen verfügbarer Komponenten gestaltet sind oder welche Integritätsbedingungen für ein Zusammenwirken erfüllt sein müssen).

.NET stellt mit dem Konzept der Assembly-Metadaten, die zur Laufzeit über Reflektion ermittelt werden können, eine geeignete Möglichkeit zur Verfügung, solche deskriptiven Komponenten-Informationen zu verwalten.

Neben den automatisch durch den Sprachcompiler generierten Metadaten (Informationen über Methoden, Eigenschaftslisten, Eigenschaftswerte etc.) können auch benutzerdefinierte Metadaten gespeichert werden.

Das folgende Listing zeigt, wie durch die Definition eigener Attributklassen im Grunde beliebige, selbst definierte Metadaten als Komponenten-Information gespeichert werden können.

 

[System.AttributeUsage(System.AttributeTargets.Class)]

 

public class InputParameterDefinition : System.Attribute

{

    public string imageType;

    public int maxImages;

 

    public InputParameterDefinition(string imageType)

    {

        this.imageType = imageType;

        maxImages = 2;

    }

}

 

Die Angabe [System.AttributeUsage(System.AttributeTargets.Class)]beschränkt die Verwendung dieser Attributklasse auf Klassen. Das definierte Attribut heißt InputParameterDefinition und kann über diesen Namen in anderen Klassen referenziert werden. Diese Attributklasse hat einen positionalen (imageType) und einen benannten (maxImages) Parameter. Während positionale Parameter als Eingabeparameter des Attribut-Konstruktors obligatorisch sind, sind benannte Parameter optional.

Diese Attributklasse beschreibt im exemplarischen Kontext einer kompositionalen Bildanalyse-Applikation die Definition eines Eingabeparameter-Typs (imageType) und die Anzahl der maximal parallel zu prozessierenden Eingabe-Bilder.

 

Diese neue Attributklasse kann nun wie folgt genutzt werden:

 

[InputParameterDefinition("tiff", maxImages = 2)]

 

    public class ImageAnalysis

    {

        public ImageAnalysis()

        {

            //some code

        }

    }

 

Durch die Angabe [InputParameterDefinition("tiff", maxImages = 2)] wird definiert, dass die Klasse ImageAnalysis nur Bilder des Typs „TIFF“ und maximale 2 parallel zu verarbeitende Bilder als Eingabeparameter entgegennimmt. Diese Informationen werden automatisch als Metadaten im ImageAnalysis-Assembly abgespeichert.

 

Zur Laufzeit kann dieses Attribut dann z.B. wie folgt ausgelesen werden:

 

Attribute[] attributes = System.Attribute.GetCustomAttributes(typeof(ImageAnalysis));

foreach (InputParameterDefinition pd in attributes) {

      if (pd != null)

      {

            Console.WriteLine("ImageType: " + pd.imageType);

            Console.WriteLine("MaxNrOfImages: " + pd.maxImages);

      }

 }

 

Falls die Attribute zur Entwurfszeit bekannt sind, lässt sich das hier präsentierte Beispiel auch mit Getter- und Setter-Methoden lösen. Häufig allerdings sind diese Definitionen a priori nicht bekannt oder ändern sich im Laufe der Zeit; für solche Szenarien eignen sich Attributklassen, um z.B. eine Liste zur Entwurfszeit unbekannter Attribute zu iterieren.

 

Thursday, August 17, 2006

C#-FAQ: Formatierung numerischer Werte  #

Um numerische Werte in C# als Zeichenketten zu formatieren, werden Standardformatbezeichner und die Methoden string.Format() oder object.ToString() genutzt. Für den Fall, dass die Standardformatbezeichner für die vorgesehenen Zwecke nicht ausreichen, können benutzerdefinierte Formatzeichenfolgen definiert werden, um das gewünschte Format zu ermöglichen. Dieser Beitrag beschäftigt sich mit drei typischen Formatierungsanforderungen:

 

  1. Begrenzung von Dezimalstellen
  2. Tausendertrennzeichen
  3. Exponential-Schreibweise

1. Begrenzung von Dezimalstellen

Um die Anzahl der Dezimalstellen einer Fließkommazahl zu begrenzen, kann der Standardformatbezeichner F genutzt werden. Dazu wird die gewünschte Anzahl der Nachkommastellen dem Bezeichner F als Suffix hinzugefügt. Das folgende Listing zeigt, wie die Anzeige eines Double-Werts auf zwei Nachkommastellen begrenzt werden kann.

 

double myDouble = 12.129;

Console.WriteLine(myDouble.ToString("F2"));

 

Die Ausgabe des myDouble-Werts lautet 12,13. Bei der Formatierung dieser Ausgabenzeichenfolge wird automatisch auf die zweite Nachkommastelle gerundet.

 

Die im Listing dargestellte Formatierungsanweisung F2 begrenzt die Ausgabe auf zwei Dezimalstellen. Falls die zu formatierende Zahl jedoch keine Nachkommastellen hat, wird die Anzahl der gewünschten Nachkommastellen mit Nullen aufgefüllt. D.h., dass z.B. die Zahl 1202 mit der Formatangabe F2 zu 1202,00 formatiert wird.

Falls dies nicht gewünscht ist, kann man eine benutzerdefinierte Formatzeichenfolge folgendermaßen definieren: 0.##. Diese Formatzeichenfolge bewirkt, dass maximal zwei Nachkommastellen dargestellt werden. Die Angabe des Rautenzeichens bedeutet hier eine optionale Darstellung der Nachkommastellen. Das folgende Listing zeigt den Einsatz der benutzerdefinierten Formatzeichenfolge:

 

double myDouble1 = 12.129;

Console.WriteLine(myDouble1.ToString("0.##"));

double myDouble2 = 1202;

Console.WriteLine(myDouble2.ToString("0.##"));

 

Die Ausgabe des myDouble1-Werts lautet 12,13,  während die zweite Ausgabe 1202 lautet.

 

2. Tausendertrennzeichen

Ein weiterer häufiger Formatierungswunsch ist die Anzeige von Tausendertrennzeichen (ein Punkt nach jeder dritten Stelle vor dem Komma). Diese Formatierung kann in C# recht komfortabel durch den Standardformatbezeichner N erreicht werden. Dabei kann analog zum Formatbezeichner F die Anzahl der darzustellenden Nachkommazahlen als Suffix angegeben werden.

Das folgende Listing zeigt einen möglichen Einsatz des Formatbezeichners N:

 

double myDouble1 = 123456;

Console.WriteLine(myDouble1.ToString("N2"));

double myDouble2 = 123456.457;

Console.WriteLine(myDouble2.ToString("N2"));

 

Die Ausgabe im ersten Fall lautet 123.456,00. Im zweiten Fall lautet die Ausgabe 123.456,46.

 

3. Exponential-Schreibweise

Um eine Zahl in Exponential-Schreibweise darzustellen (etwa weil die Zahl sehr groß bzw. sehr klein ist), kann man den Standardformatbezeichner E verwenden. Das folgende Listing zeigt zwei Beispiele, die in Exponential-Schreibweise formatiert werden:

 

double myDouble1 = 0.00001234;

Console.WriteLine(myDouble1.ToString("E"));

double myDouble2 = 1234456.34;

Console.WriteLine(myDouble2.ToString("E"));

 

Die erste Ausgabe lautet 1,234000E-005, die zweite 1,234456E+006. Der Exponent besteht aus einem Plus- oder Minuszeichen und mindestens drei Ziffern. Ggf. wird der Exponent durch Nullen ergänzt, um diesem Mindestwert zu entsprechen.

 

Hinweis: Die Ausgabe der Ergebniszeichenfolge wird von den Ländereinstellungen der Systemsteuerung beeinflusst. Die hier dargestellten Beispiele sind gültig für eine deutsche Ländereinstellung.

Auf den MSDN-Seiten findet sich eine detaillierte Übersicht der Standardformatbezeichner.

 

Monday, August 14, 2006

Attribute in .NET  #

Attribute sind eine Möglichkeit, zusätzliche Metadaten einer Assembly hinzuzufügen. Ein Beispiel für ein solches Attribut ist [Serializable]. So könnte ein Code-Ausschnitt aussehen:

[Serializable]
public class Adresse {

String vorname;
String nachname;

...
}

Durch Hinzufügen des Attributes [Serializable] ist es jetzt möglich, Objekte dieser Klasse bspw. in eine Datei abzuspeichern und zu einem späteren Zeitpunkt wieder einzulesen, ohne dass man eigenen Code programmieren muss.

Ein anderes nützliches Attribut ist [Obsolete]. Hier ein Beispiel:

[Obsolete, "Diese Klasse ist veraltet, bitte benutzen Sie stattdessen die Klasse Transporter"]
public class Bus {

int leistungKW;
String ziel;

...
}

Der C#-Compiler überprüft, ob die obsolete Klasse verwendet wird. Beim Kompilieren führt diese Anweisung zu einem Fehler:

Bus b = new Bus();

Im Ausgabefenster erscheint der Text, den wir im Attribut spezifiziert haben.

Hier noch die wichtigen Punkte zu Attributen:

  • Attribute sind Klassen die von System.Attribute abgeleitet sind.
  • Attribute fügen zusätzliche Metadaten der Assembly hinzu.
  • Attribute müssen von anderen Komponenten interpretiert (z.B. C#-Kompiler bei [Obsolete]) werden, ansonsten haben sie keinen Effekt.

Man kann auch eigene Attribute spezifizieren, dies wird demnächst erklärt.

Wednesday, August 02, 2006

Erstes HowTo Dokument zur Serverseitigen Bilderzeugung  #

Das erste HowTo Dokument aus der Serie zur serverseitigen Bilderzeugung ist im Download-Bereich verfügbar.
Es beschreibt die Grundlagen um dynamisch Grafiken zu erzeugen, die auf Webseiten dargestellt werden sollen. Es wird eine einfache Web-Applikation erstellt, die ein Textfeld enthält. Der Text, den ein Benutzer eingibt, wird in eine Grafik umgewandelt und als Bild in der Selben Seite angezeigt.

Archiv

© 2008 Fraunhofer FIT - Powered by: newtelligence dasBlog 1.8.5223.2 - Sign In

Feeds: RSS 2.0 | Atom 1.0