Automatische Eigenschaften
Bei automatischen Eigenschaften handelt es sich um ein Feature, bei dem der Compiler automatisch die privaten Felder einer Eigenschaft setzt. Der ein oder andere hat sich vielleicht schon über das "seltsame" Verhalten des Codesnippets in Visual Studio 2008 gewundert,
C#-Code: |
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public string FirstName { get; set; }
|
Erweiterungsmethoden
Durch Erweiterungsmethoden können zum Beispiel zu versiegelten Typen Methoden hinzugefügt werden. Es bestand das Problem auf IEnumerable<T> Methoden aufzurufen. Allerdings kann man ja dem Interface keine Methoden nachträglich hinzufügen. Es sei denn, man nimmt in Kauf das ein gewisse Anzahl von Anwendungen mit diesem Framework nicht mehr funktionieren würden. Erweiterungsmethoden müssen in einer statischen Klasse, als public und statisch definiert sein. Der erste Parameter wird mit einem this vor dem Datentyp gekennzeichnet. Daran und an dem Schlüsselwort static erkennt der Compiler die Erweiterungsmethode.
Beispiel für eine Erweiterungsmethoden
C#-Code: |
public static bool IsInRange( this int source, int min, int max )
{
return ( source > min && source < max );
}
public static T Where<T>( this IEnumerable<T> source, Func<T, bool> func )
{
}
|
Objektinitialisierer
Objekte werden ja normalerweise Konstruktoren oder Properties initialisiert. Das funktioniert in C# 3.0 etwas einfacher. Das ist aber keine Magie, auch keine neuen MSIL Anweisungen. Der Compiler wandelt es um und ruft einfach nur die Setter auf.
C#-Code: |
Person person = new Person { FirstName = "Max", LastName = "Mustermann" };
|
Die Konstruktorklammern müssen nicht, können aber mitgeschrieben werden. Es kann auch ein benutzerdefinierter Konstruktor erstellt werden, um die Initialisierung eines Members zu erzwingen.
Collectioninitialisierer
Wie es Objektinitialisierer gibt, gibt es auch Collectioninitialisierer. Was nun selbsterklärend sein sollte.
C#-Code: |
List<Person> persons = new List<Person>
{
new Person { FirstName = "Max", LastName = "Mustermann" },
new Person { FirstName = "Tina", LastName = "Tester" }
};
|
Implizit typisierte lokale Variablen
In C# 3.0 wird bzw. kann der Datentyp einer Variablen automatisch vom Compiler bestimmt werden. Dies geschieht über das Schlüsselwort var. Vorweg, diese Art der Zuweisung ist typsicher. Ist einer Variable einmal ein Typ vom Compiler zugewiesen worden, kann man dieser keinen anderen Datentyp mehr zuweisen.
C#-Code: |
var intValue = 1;
Console.WriteLine( intValue.GetType() );
|
Es sind aber ein paar Dinge zu beachten.
- var darf nicht verwendet werden:
- als Member in Klassen und Strukturen
- als Funktionsparameter
- als Rückgabewert einer Funktion
- var muss bei der Deklaration sofort initialisiert werden
- var darf nicht mit null initialisiert werden
Anonyme Typen
Aus LINQ Abfragen können von Objekten einige, alle oder mehr Eigenschaften in einem neuen Objekt zurückgegeben werden.
Beispiel:
C#-Code: |
IEnumerable<PersonWithFullName> query = from c in customers
select new PersonWithFullName
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
};
|
Dafür habe ich eine Klasse PersonWithFullName geschrieben. Wie man sich schnell vorstellen kann, kann das sehr ausufernd werden und zu einer "Klassenexplosion" führen. Dafür wurden anonyme Typen eingeführt. Bei anonymen Typen legt der Compiler den Typ an.
C#-Code: |
var query = from c in customers
select new { c.FirstName, c.LastName, FullName = c.FirstName + " " + c.LastName };
|
Es wird nach dem new einfach ein Objekt initilisiert und einer Variable mit dem Typ var zugewiesen. Daraus entsteht in diesem Fall ein IEnumerable<%TypDesAnonymenTypen%>.
Lambda Expressions
Der Nachfolger von anonymen Methoden. Eine Art Funktionszeiger. Das im ersten Moment auffälligste an einer Lambda Expression ist der Doppelpfeil ( => ). Links von dem Doppelpfeil steht die Parameterliste und rechts der Ausdruck. Der Rückgabetyp wird aus dem Typ des Ausdrucks bestimmt.
C#-Code: |
int[] values = { 1, 3, 4, 6, 88, 66, 453 };
Array.ForEach( values, i => Console.WriteLine( i ) );
|
Das i vom Typ int sein muss, kann der Compiler aus values ableiten. Diese Lambda Expression entspricht folgender anonymen Methode:
C#-Code: |
Array.ForEach<int>( values, delegate (int i) { Console.WriteLine(i); } );
|
Diese anonyme Methode kann man auch folgendermaßen ausdrücken.
C#-Code: |
Array.ForEach<int>( values, ShowNumbers );
private void ShowNumbers( int i )
{
Console.WriteLine( i );
}
|
Weiteres Beispiel für Lambda Expressions:
C#-Code: |
( a, b ) => a + b
Func<int, int, int> myFunc = ( a, b ) => a + b;
|
Func ist ein delegate der mit dem .NET Framework 3.5 eingeführt wird und in vielen Erweiterungsmethoden zum Einsatz kommt.
Bei den meisten Spracherweiterungen sieht man die Nützlichkeit und den Sinn wohl erst im Einsatz mit LINQ.
Suchhilfe: Spracherweiterung