Archiv des Tags ‘c#’

Cast<> und OfType<> Unterschied

Montag, den 3. November 2008

LINQ bietet extra für den Umgang mit nicht generischen Collections die beiden Extensionmethoden Cast<> und OfType<>. Mit denen ist es möglich den Inhalt einer nicht generischen Collection wie zum Beispiel ArrayList umzuwandeln. Nehmen wir folgendes Beispiel:

public class Person {   
   public string Surname  { get; set; }
   public string LastName { get; set; }
}
ArrayList list = new ArrayList {  
   { new Person { Surname = "Alfons", LastName = "TheFirst" },   
   { new Person { Surname = "Alfons", LastName = "TheSecond" }
};

Wie ihr sicherlich wisst bekommt man beim iterieren durch die ArrayList wie oben aufgezeigt immer eine Referenz auf ein System.Object. Mit den beiden LINQ Operatoren Cast<> und OfType<> kann man nun die Objektreferenzen in die konkrete Klasse Person “casten” und bekommt bei einem LINQ Query immer ein IEnumerable<Person> zurück. Dies würde folgendermassen aussehen:

// Query syntax
var persons = (from p in list.Cast<Person>()
               select p where p.LastName == "TheSecond");
// Method chaining
var persons = list.Cast<Person>().
                        Where(p => p.LastName == "TheSecond");

Doch was ist nun der Unterschied zwischen den beiden Operatoren? Der Unterschied ist eigentlich schnell erklärt. Der Cast<> Operator versucht jedes Element in der Collection zum entsprechenden Typen zu Casten. Ist der Cast nicht erfolgreich so wird eine Exception geworfen und die Ausführung des Queries beendet. Mit dem OfType<> Operator wird versucht das Element zu Casten und wenn es nicht erfolgreich ist, wird einfach das Element in der Collection ausgelassen.

Dies ist vor allem nützlich, da man bei nicht generischen Collections nicht garantieren kann, dass immer die gleichen Elemente in die Colllection abgefüllt werden. So wäre es durchaus zulässig, dass jemand in der obigen Arraylist noch

list.Add("Ätschbätsch");

hinzufügt. Nähme man dann den Cast<> Operator so wurde die Ausführung des Queries scheitern. Bei OfType<> würde das Element “Ätschbätsch” einfach nicht berücksichtigt.

C# ?? Operator

Freitag, den 2. Mai 2008

Einige von euch können sich sicher an meinen Artikel über den C# Operator ?? erinnern. Hier noch eine kleine Ergänzung. Mit dem ?? Operator kann man sich gerade bei den lästigen Abfragen ob ein Objekt null ist viel Schreibarbeit sparen. So kann man zum Beispiel folgendes Codestatement

if(name == null) {
   Console.WriteLine("Unspecified");
} else {
   Console.WriteLine(name);
}

mit dem ?? Operator folgendermassen schreiben

Console.WriteLine(name ?? "Unspecified");

Irgendwie recht sexy oder nicht? Sogar bei Objekten die mit Lazy evaluation erzeugt werden, kann der Code sehr sexy gehalten werden (siehe unten)

public User TheUser
{
  get { return theUser ?? (theUser = new User()); }
}

Laut der C# Spezifikation ist der ?? Operator sogar threadsafe. Hier eine sehr schöne Erklärung von Ian Griffiths

The C# 2.0 specification says that the left hand side is evaluated, and if that’s non-null, that becomes the result.

It’s worded such that it says the left hand side is evaluated once, and the right hand side is either not evaluated at all, or it’s evaluated once.

The race condition would only arise if the left hand side were evaluated more than once. Since it’s only evaluated once, and the resulting value is only used if it’s non-null, you’ll only ever get a non-null value from the left hand side.

http://www.interact-sw.co.uk/iangblog/

Resharper

Dienstag, den 11. März 2008

Ich bekam heute gerade eine fachgerechte Einführung in das von JetBrains entwickelte Add-in für Visual Studio mit dem Namen Resharper. Resharper erleichter das Entwickeln mit Visual Studio 2005 oder höher mit einigen wirklich nützlichen Tools und Kniffen.

Was kann überhaupt Resharper?

Die Verbesserungen die Resharper mitbringt können in folgende Kategorien unterteilt werden:

  • Codeanalyse für C#
  • Code Templates
  • Xaml Support
  • Navigation und Suche
  • Coding Assistenten
  • Code Refactoring
  • Code Generierung
  • Code Formatierung
  • Cross-Language Funktionalität
  • XML Support
  • ASP.NET Support
  • Unit Testing
  • NAnt and MS Build Scripts Editierung
  • Offene API

Codeanalyse für C#

Resharper macht konkrete Vorschläge bereits während der Eingabe und zeigt diese dem Entwickler an. So schlägt Resharper im untenstehenden Screenshot z.B. vor die Basisklasse IEnumerable<string> als Typ für den Methodenparameter zu nutzen.

suggestion_1

Resharper bietet ebenfalls sogenannte Quickfixes an. Diese Quickfixes sind konkrete Vorschläge wie ein bestehendes Problem oder eine Unschönheit gelöst werden könnten.

Error_R2

Resharper überprüft bereits während der Eingabe auf mögliche Wertefehler und Nullreference-Exceptions. So können Fehler die vielleicht in der Hitze des Gefechts übersehen würden schon gar nicht entstehen.

valueAnalysis

Code Templates

Resharper bietet vorgefertigte Templates die während der Eingabe viel Schreibaufwand ersparen können. Neben den in Visual Studio üblichen Templates wie zum Beispiel für den foreach Loop gibt es noch zahlreiche weitere nützliche Templates.

Code Formatierung

Resharper bietet erweitertes Syntaxhighlighting für den Code an wie zum Beispiel das Highlighten von Feldern, lokalen Variablen, Typen etc. Nebenbei bietet Resharper Shortcuts für das Formatierung des Quellcodes oder das Reorganisieren der Imports an. Resharper ermöglicht das automatische Layouting von Membervariablen und Typen nach vordefinierten Layouts.

Coding Assistenten

Resharper kann sogenannte Smart-Code Completion, d.h. wenn eine Methode aufgerufen wird, zeigt die Code Completion nur noch Elemente in der entsprechenden Klasse an, die überhaupt in Frage kämen um der Methode zu übergeben werden. Somit sind die Auswahllisten viel übersichtlicher.

code_completion_smart_C

Resharper unterstützt die Smartactions. So erkennt zum Beispiel Resharper im untenstehenden Code, dass es besser wäre die Stringformatschreibweise zu verwenden und schlägt dies vor. Falls man es annimmt, sieht dann der Code folgendermassen aus (siehe Screenshot 2).

context_action_C_1

context_action_C_2

Resharper unterstützt sogenannte Parameterinfo. Dies sind zusätzliche und übersichtlich aufbereitete Informationen über die Parameter einer Methode oder eines Konstruktors.

ParameterInfo_R2

Weitere Infos

Resharper bietet noch viele weitere Möglichkeiten. Jene die mehr darüber erfahren möchten, können die weiteren Informationen auf folgender Webseite beziehen:

http://www.jetbrains.com/resharper/features/index.html

Und was kostet der Spass?

image

Richtiges Invoke von UI Controls

Samstag, den 19. Januar 2008

Zu diesem Thema gibt es meiner Meinung nach im Netz nicht viel schlaue Links und Hinweise, da wollte ich mal ein bisschen aufräumen. Aber zuerst einmal um was es da genau geht.

Wenn man mit dem Visual Studio ein GUI erstellt und auf diesem GUI zum Beispiel eine Textbox hinzufügt , diese GUI dann kompiliert und ausführt, dann laufen alle GUI Operationen im sogenannten Main- oder auch UI-Thread. Dieser Thread ist zuständig für das richtige Updaten, Zeichen etc. der Benutzerelemente.

Programmiert man eine Funktion die viel Rechenzeit braucht und führt diese Funktionen in einem neuen Thread aus, so muss man die Crossthreadingcalls beachten, wenn man aus dem neu erstellten Thread auf die Benutzerelemente des Mainthreads zugreifen will (um zum Beispiel in der Textbox einen Text hinzuzufügen). Denn greift man ohne zusätzliche Sicherheit einfach aus dem zweiten Thread auf das Text Property der Textbox zu, so kann aus unter Umständen dazu führen, dass zwei Thread s zur gleichen Zeit auf die Textbox zugreifen und es kommt zu unvorhersagbaren Verhalten auf dem GUI. Doch wie kann man dies umgehen?

Die Lösung heisst Delegates und Control.Invoke().

Nehmen wir an wir haben eine Methode MyMethod du jedesmal wenn Sie von einem anderen Thread aufgerufen wird auf dem GUI den Text eines Labels myControl auf “Vom Thread aufgeweckt!” setzt. Damit die Methode MyMethod threadsafe aufgerufen werden kann, muss folgendes Codesegment implementiert werden:

Methode ohne Parameter und zugehöriges Delegate

Private delegate void MyMethodDelegate();
Private void MyMethod() {
	if(myControl.InvokeRequired) {
		myControl.Invoke(new MyMethodDelegate(MyMethod));
		return;
	}
	// Add rest of the code here
        myControl.Text = "Vom Thread aufgeweckt!";
}

Der Ablauf des obigen Codesegments ist folgendermassen. Man definiert ein Delegate (quasi typensicherer Methodenpointer), das später auf die Methode MyMethod “zeigt”. Danach prüft man in der eigentlichen Methode über myControl.InvokeRequired ob das Control aus einem anderen Thread angesprochen wurde. Ist dies der Fall, so führt man ein Invoke auf myControl über myControl.Invoke mit dem Delegate MyMethodDelegate durch und übergibt dem Delegate die aufgerufene Methode (hier MyMethod) als Parameter. Nach dem Invoke verlässt man die Methode direkt wieder über die Anweisung return;. Der eigentliche Zugriff auf das Control myControl erfolgt dann im Codeblock // Add rest of the code here.

Die Logik dahinter ist, dass durch den Aufruf von Inkvoke auf das Control, wird über das Delegate die Methode nach einmal aufgerufen und der zugreifende Thread meldet sich quasi beim UI-Thread an und wartet, bis dieser den Zugriff auf das Control frei gibt. Sobald dies der Fall ist, kann der Thread in die Methode und dieses Mal ist das Flag InvokeRequired auf false gesetzt und es wird nur der eigentliche Codeblock bei // Add rest of the code here ausgeführt.

Doch wie funktioniert das Ganze, wenn die Methode MyMethod ein oder mehrere Parameter entgegen nimmt? Hier ist der Codeauszug:

Methode mit Parameter und zugehöriges Delegate

Private delegate void MyMethodWithParameterDelegate(string message);
Private void MyMethodWithParameter(string myParameter) {
	if(myControl.InvokeRequired) {
		myControl.Invoke(new
MyMethodWithParameterDelegate(MyMethodWithParameter), new object[]{ myParameter });
		return;
	}
	// Add rest of the code here
        myControl.Text = myParameter;
}

Der Ablauf ist wieder genau gleich, einfach wird in diesem Fall ein Delegate mit Parameter spezifiziert und beim Invoke wieder ein Delegate erstellt und die Parameter für die Methode als Objektarray übergeben. That’s it!

Viel Spass beim Ausprobieren…

Nullable Types in C#

Donnerstag, den 13. Dezember 2007

Heute möchte ich kurz auf die Nullable Types in C# eingehen. Dabei sollen folgende Fragen geklärt werden:

  • Was sind Nullable Types?
  • Wozu braucht es Nullable Types

Allgemein sollte bekannt sein, dass in C# Referenzen auf Objekte auf null gesetzt werden können. Bei primitiven Datentypen wie int, float etc. ist dies aber nicht möglich. Folgende Codesequenz würde als in C# zu einem Kompilerfehler führen:


int zahl = null;

Der meist-gesehene Ansatz um die primitiven Datentypen zu initialisieren, war lange Zeit, dass man z.B. einfach die Integer mit “-1″ vorgeladen hat. Dieser Ansatz ist aber nicht wirklich elegant und musste jeweils entsprechend dokumentiert werden. Nun kommen die Nullable Types ins Spiel. Nullable Types werden in C# mit einen “?” nachgestellt dem primitiven Datentyp gekennzeichnet. Der obige Code würde also folgendermassen aussehen:


int? zahl = null;

Nullable Types haben zwei wichtige Properties die nun ins Spiel kommen. Zum einen ist dies das Property Value, das den Wert des Types beinhaltet und zum andern das Property HasValue das True oder False liefert, falls Value gesetzt ist oder nicht. Das Property Value wird automatisch angesprochen wenn man ein Code wie den untenstehenden schreibt:


int result = zahl + 42;

Ist aber zahl == null, so gibt das obige Codebeispiel eine Runtimeexception. Jetzt kann der Entwickler einfach folgende Codezeile schreiben:


if(zahl.HasValue) {
int result = zahl + 42;
}

Elegant ist auch, dass man die Möglichkeit hat einen Defaultwert bei Nullable Types zurückzugeben, falls der Nullable Type null ist. Die funktioniert folgendermassen:


int? zahl1 = null;
int zahl2 = zahl1 ?? 42;

Der obige Code zeigt in der zweiten Zeile wie ein Defaultwert gesetzt werden kann. Falls zahl1 == null wird zahl2 mit 42 initialisiert!

Mehr zu Nullable Types: