Archiv

Posts Tagged ‘C#’

.Net Framework übergreifend entwickeln mit Portable Class Libraries

16. April 2012 Kommentare aus

Mittlerweile gibt es neben dem .Net Framework 4 auch Silverlight, Windows Phone 7 und Xbox 360. Obwohl man überall in C# entwickeln kann stösst man doch schnell einmal an eine Grenze: Eine Klassenbibliothek vom vollen .Net Framework kann nicht in einem Silverlight-Projekt verwendet werden. Gleiches gilt für Windows Phone 7. Und um es noch ein wenig mühsamer zu machen sind Silverlight und Windows Phone 7 auch nicht kompatibel.

Dies zeigt sich mit dieser Fehlermeldung wenn man versucht eine *.dll einzubinden:

 

Portable Library Tools als Lösung

Eine Entdeckung der Tech Conference war für mich die Portable Class Libraries. Dieser Projekt-Typ ist vergleichbar mit einer gewöhnlichen Class Library. Allerdings kann man mehrere Framework-Plattformen als Ziel wählen.

Die einzelnen Frameworks haben eine grosse Menge an Funktionen die überall zur Verfügung stehen. So lange man in diesem Bereich bleibt ist dieser Projekttyp eine sehr gute Lösung um den Code nur einmal zu schreiben. Was genau geht und wo die Grenzen liegen ist in der MSDN gut beschrieben.

Benötigt man die Framework-Spezifischen Teile kann man immer noch mehrere Projekte machen und die *.cs Dateien verlinken.

 

Installation

Wie immer mehr Bibliotheken und Erweiterungen kann man die Erweiterung Portable Library Tools über NuGet installieren. Sobald dies gemacht ist gibt es eine neue Projektvorlage:

Über die Projekteigenschaften kann man die Zielframeworks sehr einfach auswählen:

Der wiederverwendbare Code kann nun in diesem Projekt entwickelt werden und steht Anwendungen der aktivierten Frameworks zur Verfügung.

 

Ausblick

Windows 8 wird mit Metro noch ein weiteres Framework in die .Net Welt bringen. Gemäss den Informationen aus der Tech Conference von Mitte März in Baden gibt es aber eine gute Nachricht: Visual Studio 11 (oder wie man die Version am Ende nennt) wird diesen Projekttyp bereits integriert haben. Eine Nachinstallation wird so nicht nötig sein und damit auch den Anwendern der Express-Edition zur Verfügung stehen.

 

Schlagworte: , , ,

LINQ: eine Liste anhand einer anderen Liste sortieren

30. April 2011 Kommentare aus

Ich hatte vor kurzem eine „kleine“ Herausforderung zu lösen: Als Input hatte ich eine Liste A mit Primärschlüsseln und ich sollte eine Liste B mit den dazugehörigen Objekten zurückliefern – aber in der gleichen für mich nicht nachvollziehbaren Reihenfolge wie ihre Id in Liste A erscheinen.

Die Aufgabe wäre nicht der Rede wert wenn man nach einem bestimmten Feld sortieren könnte. In dem Fall gäbe es genügend Möglichkeiten um ein Order By in LINQ oder schon in SQL durchzuführen.

 
Ein JOIN als Lösung
Auf Stackoverflow fand ich eine Antwort von Simon D die mir den Weg zeigte. Ein einfacher JOIN in LINQ löst das Problem auf eine sehr elegante Weise:

var orderedByIDList = from i in ids 
                       join o in objectsWithIDs
                       on i equals o.ID
                       select o;

 
Ein Beispiel
Um die Lösung in Aktion zu sehen habe ich diesen kleinen Code-Schnipsel zusammengestellt. Eine Liste von Personen soll nach ihren Id’s sortiert werden, so wie sie in der Liste filter festgelegt wurden. Um Daten nicht aus einer DB holen zu müssen dient die Methode GetSampleData() als Datengenerator.

void Main()
{
        List<long> filter = new List<long>(){1,3,2};
        List<Person> result = Person.GetSampleData();
        result.Dump();
        
        var orderedResult = from f in filter join r in result on f equals r.Id select r;
        orderedResult.Dump();        
}

public class Person 
{
        public long Id;
        public string LastName;
        public string FirstName;
        
        public static List<Person> GetSampleData()
        {
                List<Person> data = new List<Person>(){
                        new Person(){Id = 1, LastName = "Vettel", FirstName = "Sebastian"},
                        new Person(){Id = 2, LastName = "Massa", FirstName = "Felipe"},
                        new Person(){Id = 3, LastName = "Hamilton", FirstName = "Lewis"},
                };
                
                return data;
        }
}

Gibt man dieses Beispiel in LINQPad als “C# Program” (bei Language) ein, wird die Liste bei der 2. Ausgabe entsprechend verändert:

 
Fazit
Man sollte auch kleine Probleme nutzen um sein Wissen auszubauen. LINQ bietet einem die Möglichkeit erstaunliche Ansätze zu einer Lösung zu kombinieren und Probleme aus einem ganz anderen Blickwinkel anzugehen. Und Stackoverflow ist ein idealer Anlaufort für solche Probleme.

Schlagworte: ,

Mengenoperationen mit LINQ

28. Dezember 2010 6 Kommentare

Wie weithin bekannt ist, kann man mit LINQ (Language Integrated Query) beliebige Datenquellen abfragen. Ich bin vor kurzem auf eine weitere interessante Anwendungsmöglichkeit gestossen, die wohl nicht allen bekannt ist: Mengenoperationen.

Ich fand diese Möglichkeit als ich nach einer optimierten Version für so ein Stück Code suchte:

private static List<int> ValuesNotInSecondList(List<int> first, List<int> second)
{
    List<int> result = new List<int>();

    foreach (var i in first)
    {
        if(!second.Contains(i))
        {
            result.Add(i);
        }
    }

    return result;
}

Aus einer Liste A sollen alle Werte zurückgeliefert werden, die nicht in Liste B vorhanden sind. Diese an sich einfache Aufgabe braucht nach meinem Geschmack zu viel Code.

ReSharper hat mir diese optimierte Version vorgeschlagen:

private static List<int> ValuesNotInSecondList(List<int> first, List<int> second)
{
    return first.Where(i => !second.Contains(i)).ToList();
}

Der Code wurde schon massiv reduziert, aber irgendwie genügte mir dies noch nicht. Da in meinem konkreten Anwendungsfall in meiner ersten Liste die Werte immer nur 1x vorkommen, suchte ich weiter.

 
Differenz zweier Mengen
In Wikipedia wird die (mathematische) Differenz zweier Mengen wie folgt beschrieben:

Die Differenzmenge (auch Restmenge) von A und B ist die Menge der Elemente, die in A, aber nicht in B enthalten sind.

Und das ist eigentlich genau das, was die Methode machen soll. LINQ erweitert IEnumerable um die Methode Except, die genau dieses Verhalten implementiert:

List<int> listOdd = new List<int> { 1, 3, 5, 7, 9 };
List<int> listFibonacci = new List<int> { 1, 2, 3, 5, 8 };

List<int> resultExcept = listOdd.Except(listFibonacci).ToList();
PrintList(resultExcept); // Resultat: 7,9

In diesem Beispiel werden die Zahlen zurückgegeben, die zwar ungerade aber nicht teil meiner reduzierten Fibonacci-Folge sind.

 
Schnittmenge und Vereinigung
LINQ bietet ebenfalls eine Methode für die Schnittmenge (Intersect) und die Vereinigung (Union) an:

List<int> resultIntersect = listOdd.Intersect(listFibonacci).ToList();
PrintList(resultIntersect); // Resultat: 1,3,5

List<int> resultUnion = listOdd.Union(listFibonacci).OrderBy(i => i).ToList();
PrintList(resultUnion); // Resultat: 1,2,3,5,7,8,9 (Reihenfolge durch die Sortierung)

 
Auch mit Strings möglich
Was so schön mit Integer funktionierte, geht übrigens genauso auch mit Strings (oder jedem anderen Typ der mit EqualityComparer.Default verglichen werden kann IEquatable implementiert):

List<string> listAD = new List<string> { "A", "B", "C", "D" };
List<string> listCF = new List<string> { "C", "D", "E", "F", };


List<string> resultADexceptCF = listAD.Except(listCF).ToList();
PrintList(resultADexceptCF); // Resultat: A,B

List<string> resultADintersectCF = listAD.Intersect(listCF).ToList();
PrintList(resultADintersectCF); // Resultat: C,D

List<string> resultADunionCF = listAD.Union(listCF).ToList();
PrintList(resultADunionCF); // Resultat: A,B,C,D,E,F

 
Fazit
Für Mengenoperationen bietet LINQ spezielle Operationen an, die einem viel eigenen Code ersparen. Wichtig ist dabei aber, dass die Listen nicht mehrmals den gleichen Wert enthalten. Sonst sind es keine Mengen mehr und LINQ filtert die doppelten Werte in der Resultatmenge selber heraus.

Schlagworte: ,

Leichter debuggen mit DebuggerDisplay

10. September 2009 Kommentare aus

Der Debugger von VisualStudio zeigt einem einen Tooltip an, sobald man mit der Maus über eine Variable oder eine Klasse fährt. Je nach dem ist dieser Text mehr oder weniger hilfreich. Man hat zwar immer die Möglichkeit, die einzelnen Felder und verschachtelten Werte durchzuklicken, bis man die gewünschten Werte angezeigt bekommt. Je grösser die Klasse und je mehr Felder diese beinhaltet, desto unübersichtlicher und mühsamer wird es.

Als kleines Beispiel dient mir eine Klasse Person. Dieses repräsentiert einen Menschen und der Vor- und Nachname sind die Informationen, über die ich das Objekt zuordnen kann. Beim debuggen wäre es für mich hilfreich, genau diese Informationen im Tooltip angezeigt zu bekommen (und eine Id, sollten mehrere Personen den gleichen Namen haben). Eine ganz einfache Personenklasse kann so aussehen:

using System;

namespace DebuggerInfo
{
    class PersonBasic
    {
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public int Id { get; set; }

        public PersonBasic(String firstName, String lastName, int id)
        {
            FirstName = firstName;
            LastName = lastName;
            Id = id;
        }
    }
}

Als Tooltip wird nur der Namespace und Klassenname gezeigt:

Tooltip mit Klassennamen

Wie kann ich nun eine bessere Beschreibung bekommen?

 
Option 1: ToString() überschreiben

Die einfachste Möglichkeit um die gewünschte Anzeige zu erhalten ist das überschreiben der ToString-Methode. Dazu genügt dieses kleine zusätzliche Stück Code:

public override string ToString()
{
    return String.Format("{0} {1} {2}", FirstName, LastName, Id);
}

Der Debugger nutzt nun die ToString-Methode und liefert mir eine hilfreiche Anzeige zurück:
Tooltip mit ToString

 
Option 2: Attribut DebuggerDisplay

Ist die ToString-Methode schon überschrieben und liefert nicht die gewünschten Informationen, kann mit dem Attribut DebuggerDisplay auf Ebene der Klasse die Anzeige im Debugger geändert werden. Dies befindet sich im Namespace System.Diagnostics. Der dazugehörende Code sieht so aus:

namespace DebuggerInfo
{
    [DebuggerDisplay("Person: {LastName} {FirstName}")]
    class PersonDebug
    {
        // Klassendefinition
    }
}

Im Debugger gibt es das gewünschte Ergebnis:

Tooltip mit DebuggDisplay

 

Fazit:
DebuggerDisplay kann einem helfen, gewünschte Informationen nur für den Debugger aufzubereiten. Eine sinnvolle ToString-Methode sollte aber zu erst erstellt werden.

Schlagworte: , ,
Follow

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 245 Followern an