2 .NET Framework Class Library (FCL)
2.1 ExpandoObject
Für Fälle, in denen lediglich ein dynamisches Objekt, welches das freie Definieren von Eigenschaften und Methoden erlaubt, benötigt wird, kann seit .NET 4.0 auf die KlasseExpandoObject zurückgegriffen werden. Listing 2.1 demonstriert die Verwendung dieser Klasse. Zunächst werden dem Objekt die EigenschaftenFirstName undLastName hinzugefügt, anschließend bekommt es eine MethodeDoStuff, die als Lambdaausdruck übergeben wird, spendiert. Danach werden die beiden Eigenschaften wieder ausgelesen und die Methode wird aufgerufen.
dynamic whatever = new ExpandoObject();
whatever.FirstName ="Max";
whatever.LastName ="Mustermann";
whatever.DoStuff = new Action(() => Console.WriteLine("Hello World!"));
Console.WriteLine(whatever.FirstName +"" + whatever.LastName);
whatever.DoStuff();
Listing 2.1
2.2 Prüfung auf 64 Bit
Mit zwei Eigenschaften kann ab .NET 4.0 geprüft werden, ob die aktuelle Applikation in einem 64-Bit-Prozess läuft und ob es sich bei dem aktuellen Betriebssystem um ein 64-Bit-Betriebssystem handelt. Für Ersteres stehtIs64BitProcess zur Verfügung, für LetzteresIs64BitOperatingSystem. Ein Beispiel, das die Werte dieser beiden booleschen Eigenschaften auf der Konsole ausgibt, findet sich in Listing 2.2.
Console.WriteLine("Is64BitProcess:" + Environment.Is64BitProcess);
Console.WriteLine("Is64BitOperatingSystem :" + Environment.Is64BitOperatingSystem);
Listing 2.2
2.3 BigInteger
Für jene Fälle, in denen mit ganzzahligen Werten beliebiger Größe gerechnet werden soll, bietet .NET seit Version 4.0 eine neue Struktur namensBigInteger (System.Numeric.BigInteger) an. Damit Instanzen vonBigInteger ähnlich wie herkömmliche Integer-Werte behandelt werden können, wurden sämtliche arithmetischen Operatoren sowie Bit-, Vergleichs- und Zuweisungsoperatoren überladen. Ein Beispiel für die Verwendung dieses neuen Typs ist in Listing 2.3 zu sehen. Dabei fällt auf, dass einemBigInteger primitive Integer-Werte direkt zugewiesen werden können, ohne dafür eine eigene Instanz vonBigInteger erzeugen zu müssen. Einige Methoden, die für primitive Datentypen in der KlasseMath untergebracht wurden, finden sich als statische Methoden direkt in der KlasseBigInteger wieder. Als Beispiele solcher Methoden seien an dieser StellePow (Potenz),Abs (Absolutwert) sowieLog (Logarithmus) genannt.
BigInteger bigInt1;
BigInteger bigInt2;
bigInt1 = long.MaxValue;
bigInt1 = bigInt1 * bigInt1;
bigInt2 = bigInt1;
bigInt2 = bigInt2 + 1;
Console.WriteLine(bigInt2);
Listing 2.3
2.4 Standortermittlung
Beim Einsatz von Windows 7 besteht die Möglichkeit, unter Verwendung von Sensoren den aktuellen Standort herauszufinden. Wer einen solchen Sensor nicht sein Eigen nennt, kann softwarebasierte Varianten im Internet zum Download finden. Nach der Installation muss der Sensor in der Systemsteuerung unterOrtung und andere Sensoren aktiviert werden.
Sensoren dieser Art können ab .NET 4.0 angesprochen werden, wie in Listing 2.4 demonstriert. Dieses Beispiel ermittelt über eine Instanz vonGeoCoordinateWatcher die aktuellen Koordinaten (Längengrad, Breitengrad) und versucht mit diesen unter Verwendung einesCivicAddressResolver die dazugehörige zivile Adresse herauszufinden. Die MethodeTryStart startet die Verwendung des Sensors. Das erste Argument gibt an, ob der Dialog, der den Benutzer um Erlaubnis zur Verwendung der aktuellen Position bittet, unterdrückt werden soll. Wird dieser Dialog unterdrückt, muss bereits die Verwendung des Sensors durch den Benutzer bewilligt worden sein, damit der aktuelle Standort ermittelt werden kann. Das zweite Argument gibt an, wie viel Zeit in die Ermittlung der aktuellen Position maximal investiert werden darf. Der boolesche Rückgabewert gibt Aufschluss über den Erfolg der Standortermittlung. Im betrachteten Beispiel werden die ermittelten Geodaten sofort verwendet. Um über Standortänderungen informiert zu werden, kann zusätzlich das EreignisPositionChanged der KlasseGeoCoordinateWatcher verwendet werden. Über die EigenschaftMovementThreshold kann dabei in Metern angegeben werden, nach welcher Distanz dieses Ereignis aufgerufen werden soll.
GeoCoordinateWatcher watcher = new
GeoCoordinateWatcher(GeoPositionAccuracy.Default);
bool started = watcher.TryStart(false, TimeSpan.FromMilliseconds(1000));
if (!started) Console.WriteLine("GeoCoordinateWatcher timed out on start.");
CivicAddressResolver resolver = new CivicAddressResolver();
if (!watcher.Position.Location.IsUnknown)
{
CivicAddress address = resolver.ResolveAddress(watcher.Position.Location);
if (!address.IsUnknown)
{
Console.WriteLine("Country: {0}, Zip: {1}, City: {2}",
address.CountryRegion,
address.PostalCode,
address.City);
}
}
Listing 2.4
2.5 Interprozesskommunikation mit Memory-mapped Files
Memory-mapped Files erlauben das Bereitstellen von Informationen über den Hauptspeicher und werden gerne zur Interprozesskommunikation eingesetzt. Listing 2.5 zeigt, wie ein solches Memory-mapped File erzeugt und beschrieben werden kann. Zunächst wird ein Memory-mapped File mit dem NamensomeMemoryMappedFile und einer maximalen Größe von 1 000 Bytes erzeugt. Zum Zugriff auf dieses File wird anschließend mittelsCreateViewStream ein Stream erzeugt, der den Zugriff auf einen Ausschnitt (View) des Memory-mapped Files gewährt. Da an dieser Stelle keine weiteren Parameter angegeben werden, erstreckt sich dieser Ausschnitt auf das gesamte File. Überladungen dieser Methode erlauben jedoch die Angabe eines Offsets sowie einer Länge für den zu bearbeitenden Ausschnitt. Darüber hinaus existiert auch eine Überladung, die zusätzlich die Angabe von Zugriffsberechtigungen erlaubt. Anschließend wird über einenBinaryWriter der StringHello World in den Stream geschrieben und die Datei geschlossen. Im zweiten Teil von Listing 2.5 wird das Memory-mapped File erneut geöffnet und gelesen.
using (var file = MemoryMappedFile.CreateNew("someMemoryMappedFile", 1000))
{
using (var stream = file.CreateViewStream())
{
var writer = new BinaryWriter(stream);
writer.Write("Hello World!");
}
}
[...]
using (var file = MemoryMappedFile.OpenExisting("someMemoryMappedFile"))
{
using (var stream = file.CreateViewStream()) {
var reader = new BinaryReader(stream);
Console.WriteLine(reader.ReadString());
}
}
Listing 2.5
2.6 Auf Textdateien mittels LINQ zugreifen
Als Alternative zuFile.ReadAllLines wird ab .NET Version 4.0 eine MethodeReadLines bereitgestellt, die anstatt eines String-Arrays einIEnumerable<string> zurückliefert. Bei einer Iteration diesesIEnumerable werden die Zeilen nach und nach geladen. Analog dazu stehen mitAppendAllLines undWriteAllLines Methoden zur Verfügung, welche die Zeilen aus einemIEnumerable<string> an eine Datei anhängen bzw. eine Datei mit diesen Zeilen erstellen oder überschreiben. In dieselbe Kerbe schlagen drei neue Methoden der KlasseDirectoryInfo:EnumerateFiles,EnumerateDirectories undEnumerateFileSystemInfos. Diese Methoden liefern einIEnumerable mit den Dateien und/oder Verzeichnissen, die sich innerhalb des jeweiligen Ordners befinden.
Da LINQ auf den Möglichkeiten vonIEnumerable basiert, erlauben diese neuen Methoden ein einfaches und elegantes Formulieren von Abfragen, welche sich auf Dateien und Dateiinhalte beziehen. Die LINQ-Abfrage in Listing 2.6 ermittelt mit diesen Methoden beispielsweise jene Zeilen aus sämtlichen CSV-Dateien des aktuellen Ordners, bei denen sich in der ersten Spalte der Wert 1 wiederfindet. Das Ergebnis dieser Abfrage – einIEnumerable<string> – wird anschließend an die zuvor erwähnte MethodeWriteAllLines übergeben, um die gefundenen Zeilen in der Dateiresult.txt zu hinterlegen.
DirectoryInfo dir = new DirectoryInfo(".");
var info =
from file in Directory.EnumerateFiles(".","*.csv")
from line in File.ReadLines(file)
where line.Split(';')[0] =="1"
select file +":" + line;
File.WriteAllLines("result.txt", info);
Listing 2.6
2.7 Erweiterungsmethode „String.Truncate()“
In Visual Basic ist dieLeft()-Funktion ein wichtiges Instrument, um die Länge einer Zeichenkette zu begrenzen, zum Beispiel vor der Übergabe an ein Datenbankfeld begrenzter Länge. Überstehende Zeichen werden dabei abgeschnitten. In C# gibt es diese Funktion nicht, man muss immer mitString.SubString() arbeiten. Aber Achtung: Wenn die...