Alphabetischer Index mit C# und LINQ 👍 👎

Häufig kann es sinnvoll sein, eine Liste nach Anfangsbuchstaben gruppiert darzustellen. Dies kann unter C# in Verbindung mit LINQ sehr einfach und elegant geschehen, wozu wir wie üblich ein kleines Beispiel durchgehen.

Konkret möchten wir Personen nach Anfangsbuchstabe von LastName gruppiert und darin wiederum nach LastName sortiert ausgeben. Auf Grund der Trivialität der Klasse verweise ich auf das im Artikel zu Eigenschaften in C# präsentierte Beispiel und fahre direkt mit der Liste fort:
Liste von Personen
01020304050607080910111213141516171819202122
List<Person> personList = new List<Person>() {    new Person() {        FirstName = "Harald",        LastName = "Müller"    },    new Person() {        FirstName = "Helga",        LastName = "Schmidt"    },    new Person() {        FirstName = "Karl",        LastName = "Schneider"    },    new Person() {        FirstName = "Olaf",        LastName = "Fischer"    },    new Person() {        FirstName = "Saskia",        LastName = "Weber"    }};
Nun führen wir die Gruppierung ganz einfach per GroupBy(…) aus und speichern dies mit den dazugehörigen Listen per ToDictionary(…) direkt in ein Dictionary:
Liste gruppiert abspeichern
010203
Dictionary<char, List<Person>> personStructure = personList    .GroupBy(p => p.LastName[0])  // Gruppierung nach erstem Buchstaben des Nachnamens    .ToDictionary(k => k.Key, v => v.ToList());
Anschließend können wir die Struktur beispielsweise durchlaufen und auf einer Webpräsenz ausgeben:
Struktur durchlaufen
01020304050607080910
foreach(KeyValuePair<char, List<Person>> data in personStructure) {    // "data.Key" enthält den Anfangsbuchstaben
foreach(Person person in data.Value.OrderBy(p => p.LastName)) {
/** * "person" enthält nun jeweils eine zu eben * diesem Anfangsbuchstaben passende Person. **/ }}
Das Ergebnis einer solchen Vorgehensweise lässt sich u. a. in der neuen Ansicht der Bezirkszuordnungen auf meinem Städteportal für Berlin und Hamburg betrachten. Für diese einfache Darstellung kommt übrigens noch ein zusätzlicher kleiner LINQ-"Trick" mit Select(…) zum Einsatz. Für unser Beispiel könnten wir dazu die innere Schleife schlicht durch Folgendes ersetzen und damit Vor- und Nachname per Komma separiert ausgeben:
Einfache Zeichenketten-Konkatenierung
01
String.Join(", ", data.Value.Select(p => p.FirstName + " " + p.LastName));

Städteportal umfangreich erweitert 👍 👎

In letzter Zeit war es hier etwas ruhiger im Blog. Das liegt einerseits daran, dass ich beruflich recht eingespannt bin und andererseits daran, dass ich ein den meisten regelmäßigen Besuchern dieser Webpräsenz sicherlich bereits bekanntes Projekt stark erweitert habe: Mein Portal für die beiden Stadtstaaten Berlin und Hamburg.

Ich erlaube mir demnach eine kleine zusätzliche Werbung dafür und fasse ein paar Neuerungen kurz zusammen:
  • Bahnhöfe besitzen nun die Information,
    • ob sie sich ober-/unterirdisch befinden,
    • in welchem Tarifbereich sie sich befinden
    • und ob sie barrierefrei erreichbar sind.
  • Einige dutzend Bezirkszuordnungen wurden erfasst oder präzisiert.
  • Über hundert neue Geo-Koordinaten wurden erfasst und mehrere dutzend Wikipedia-Artikel ergänzt.
  • Es können Entfernungsberechnungen auf Basis der Koordinaten (per Orthodrome) durchgeführt werden.
  • Es existieren jeweils zusätzlich separate RSS-Feeds für Berlin und Hamburg.
  • Es existiert ein (Veranstaltungs-)Kalender mit Feiertagen.
  • Es existiert ein neuer Abschnitt für Parkanlagen.
  • Es existiert ein neuer Abschnitt für das aktuelle Wetter mit Vorhersage (per wetter.com).
Darüber hinaus wurde der SOAP-Webservice freigeschaltet, welcher die meisten Daten und Zuordnungen für eigene Anwendungen zur Verfügung stellt. Es gibt dazu eine Dokumentation und Beispiele für C# und PHP.

Für Interessierte sei zum Schluss auch noch erwähnt, dass das gesamte Portal ebenso wie diese Webpräsenz hier auf ASP.NET MVC mit C# basiert. Der Zugriff auf die Datenbank erfolgt per ADO.NET Entity Framework mit LINQ.

XML-Dokumentationskommentare in C# 👍 👎

Zwar nutzt sicherlich jeder sehr gerne die von Visual Studio eingeblendeten Kommentare während der Entwicklung mit dem .NET-Framework, bei vielen Projekten herrscht hier jedoch häufig akuter Mangel. Dabei wird einem dies für Standardkommentare besonders einfach gemacht.

Ihr müsst dazu lediglich über eine Klasse oder beliebigen Member davon (z. B. Eigenschaft, Methode) drei Schrägstriche ("///") in Folge schreiben, worauf Visual Studio automatisch einen passenden XML-Kommentarblock erstellt, den ihr vervollständigen könnt. Am besten sehen wir uns ein "fertiges" Beispiel an:
Klasse "Person" mit XML-Dokumentationskommentaren
01020304050607080910111213141516171819202122232425262728293031
/// <summary>/// Stellt eine Person dar./// </summary>public class Person {    /// <summary>    /// Liefert den Vornamen oder legt diesen fest.    /// </summary>    public string FirstName {        get;        set;    }
/// <summary> /// Liefert den Nachnamen oder legt diesen fest. /// </summary> public string LastName { get; set; }

/// <summary> /// Lässt die Person sprechen. /// </summary> /// <param name="textToSay">Text, der gesprochen werden soll.</param> public void Say(string textToSay) { /* * Implementierung für Beispiel nicht notwendig. */ }}
Alle wesentlichen Bestandteile (insbesondere Rückgabewerte und Parameter) lassen sich separat beschreiben, wobei es zusätzlich immer eine Zusammenfassung gibt. Diese Informationen werden bei Verwendung dieser Klasse nun angezeigt, ganz so wie man es von integrierten Typen kennt.

Als besonders nützlich stellt sich dies selbstverständlich dann heraus, wenn die Klasse (beispielsweise als Bestandteil einer Programmbibliothek) weitergegeben und von anderen Entwicklern verwendet werden soll. Hier gibt es jedoch noch eine kleine Hürde zu bewältigen, denn unsere – mehr oder weniger – mühsam erstellten Kommentare überleben den Kompilierungsvorgang nicht. Ihr könnt Visual Studio jedoch anweisen, eine separate XML-Datei hierfür zu erstellen, welche ihr zusammen mit der DLL weitergeben könnt. Ihr findet die entsprechende Einstellung in der Projektkonfiguration unter Erstellen -> XML-Dokumentationsdatei.

Wie üblich gibt es weitere Informationen zur Verwendung im MSDN, insbesondere eine Tag-Übersicht.

Variadische Methoden in C# 👍 👎

Variadische Funktionen sind Funktionen, die eine unbestimmte Anzahl von Argumenten (→ Arität) entgegennehmen können. Das passende Stichwort an dieser Stelle für PHP-Entwickler ist hauptsächlich func_get_args. Selbstverständlich bietet beispielsweise auch Java eine entsprechende Möglichkeit. Wie ihr sicher bereits befürchtet habt, lege ich den Fokus im weiteren Verlauf jedoch auf C#. Smiley: grinning

Als Beispiel soll uns eine Methode dienen, welche uns die Summe einer beliebigen Anzahl an Zahlen liefert. Zu Vergleichszwecken erinnern wir uns zuerst einmal daran, wie dieses Problem "normal" gelöst werden kann. Die Lösung ist selbstverständlich, ein Feld zu übergeben:
Nicht-variadische Funktion zur Problemlösung
01020304050607
  // Methode definierenpublic int GetSum(int[] list) {    return list.Sum();}
// Methode verwendenint sum = GetSum(new int[] { 1, 2, 3 });
Durch eine minimale Anpassung – nämlich indem wir das params-Schlüsselwort vor dem Parameter ergänzen – wird daraus eine variadische Funktion unter Beibehaltung der bisherigen Funktionalität:
Variadische Funktion zur Problemlösung
010203040506070809
  // Methode definierenpublic int GetSum(params int[] list) {    return list.Sum();}
// Methode verwendenint sum = GetSum(1, 2, 3); // – oder, ebenfalls möglich -int sum = GetSum(new int[] { 1, 2, 3 });
Wie leicht zu sehen ist, handelt es sich soweit letztlich um eine syntaktische Variante, welche nicht unbedingt notwendig ist. Bei Methoden, die sehr häufig z. B. zwei oder drei Argumente erwarten, prinzipiell jedoch auch mehr denkbar wären, erscheint mir eine solche Möglichkeit jedoch durchaus vernünftig. Das .NET-Framework setzt u. a. bei den Methoden String.Format(…) und String.Join(…) auf dieses Vorgehen.

Zuletzt gilt es aber noch auf folgende Besonderheiten hinzuweisen:
  • params-Parameter sind generell optional (d. h. GetSum() wäre möglich)
  • params-Parameter können vor sich fest definierte Parameter besitzen, nicht jedoch danach
  • params-Parameter dürfen pro Methode lediglich einmal auftreten

Windows-Bibliotheken und NAS 👍 👎

Bei vielen Benutzern scheinen die Windows-Bibliotheken immer noch für mehr Verwirrung als Nutzen zu sorgen. Da ich diese jedoch sehr gerne verwende, möchte ich einen konkreten Anwendungsfall am Beispiel meines tatsächlichen lokalen Netzwerkes im Zusammenhang mit einem NAS erläutern.

Die Ausgangssituation stellt sich so dar, dass ich in meinem Heimnetzwerk sowohl mit einem stationären Rechner arbeite, als auch mit einem Netbook. Da ich meist für die gleiche Arbeit beide Geräte abwechselnd nutze, ergibt sich natürlich umgehend das Problem, die Daten synchron zu halten. Naheliegenderweise besitze ich deshalb zusätzlich ein NAS (für Interessierte: es handelt sich um eine Synology DiskStation*).

Ich habe dazu gemeinsame Ordner für öffentliche Bilder, Dokumente, Musik, Podcasts und Videos angelegt. Da es durchaus auch Dateien gibt, die nicht jeder sehen muss, besitzt jeder angelegte Benutzer auf dem NAS zusätzlich ein home-Verzeichnis. Auf die weiteren – durchaus interessanten – Möglichkeiten des NAS möchte ich nun aber gar nicht weiter eingehen, sondern den Komfort im Zusammenhang mit den Windows-Bibliotheken erläutern; genauer nehmen wir uns die "Bilder"-Bibliothek vor. Standardmäßig zeigt diese nach der Installation von Windows auf die Ordner "Eigene Bilder" (C:\Users\{BENUTZER}\Pictures) und "Öffentliche Bilder" (C:\Users\Public\Pictures).

Mein NAS habe ich nun so konfiguriert, dass die gemeinsamen Ordner als Freigabe zur Verfügung stehen. Für am System angemeldete Benutzer steht außerdem das bereits erwähnte Heimverzeichnis zur Verfügung. Die Bibliotheken habe ich so abgeändert (was ganz einfach über den Eigenschaften-Dialog möglich ist), dass die alten Verzeichnis-Zuordnungen entfallen sind und stattdessen die öffentlichen Freigaben und die entsprechenden Pfade innerhalb meines Heimverzeichnisses eingetragen wurden. Den privaten Ordner habe ich darüber hinaus als Standardspeicherort festgelegt.

Praktisch kann ich nun also genauso wie zuvor arbeiten (insbesondere verhält sich dies Programmen gegenüber weitestgehend transparent), mit dem Unterschied, dass ich nicht mehr auf lokale Daten zugreife, sondern auf das NAS. Durch die Festlegung des Standardspeicherortes auf meine persönliche Freigabe landen alle auf die Bibliothek gezogenen Dokumente (zumindest erst einmal) automatisch dort. Dennoch habe ich aber über die Bibliotheken auf alle Dateien über einen Ort im Windows Explorer Zugriff, wobei ich einzelne Dateien jederzeit beispielsweise von meinem privaten in den öffentlichen Ordner verschieben kann, ohne mir um den konkreten Speicherpfad Gedanken zu machen. Ebenfalls kann nun der Zugriff von allen Geräten auf die gleiche Weise erfolgen, womit im Normalfall (man kann natürlich alles provozieren) keine Inkonsistenzen entstehen können. Für Besitzer eines Windows Phone (wie mich) ist außerdem praktisch, dass Zune – genauso wie der Windows Media Player – standardmäßig ebenfalls auf diese Bibliotheken zugreift und dadurch alle Medien problemlos auch dafür und damit auch zur Synchronisierung mit dem Smartphone zur Verfügung stehen.

Wer ebenfalls per VPN Zugriff auf ein externes Netzwerk (beispielsweise des Unternehmens) hat, kann dessen Freigaben auch einer solchen Bibliothek hinzufügen und so auch darauf zentral zugreifen. Dies finde ich auf jeden Fall deutlich komfortabler über Bibliotheken als die Auswahl über div. Netzlaufwerke. Zugegebenermaßen muss man aber wohl sagen, dass dieser Vorteil erst in ähnlichen Umgebungen wie in meinem Anwendungsfall voll zur Geltung kommt. Sofern man lediglich mit einem Rechner und ohne Netzwerkspeicher arbeitet, d. h. wahrscheinlich sowieso alle Dateien in den eigenen Ordnern ablegt, wird man von den Windows-Bibliotheken tatsächlich nicht wesentlich profitieren. Sie stören meines Erachtens nach aber auch nicht, wenn einem das Konzept der Zusammenführung verschiedener Pfade unter einem virtuellen bewusst ist.

Wer sich für die technischen Details der Bibliotheken interessiert, findet deren Definition übrigens im Verzeichnis C:\Users\{BENUTZERNAME}\AppData\Roaming\Microsoft\Windows\Libraries; die *.library-ms-Dateien enthalten XML-Code.


*) Nein, ich erhalte für diesen Link kein Geld. Smiley: tongue_out

Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche