C# 3.0 features include:
- Lambda expressions
- Extension methods
- Implicitly typed local variables
- Query comprehensions
- Anonymous types
- Implicitly typed arrays
- Object initializers
- Automatic properties
- Partial methods
- Expression trees
Lambda expressions are like miniature functions created on the fly. They are a natural evolution of anonymous methods introduced in C# 2.0, and in fact, completely subsume the functionality of anonymous methods. For example:
Func<int,int> sqr = x => x * x;
Console.WriteLine (sqr(3));
The primary use case in C# is with LINQ queries, such as the following:
string[] names = { "Tom", "Dick", "Harry" };
// Include only names of >= 4 characters:
IEnumerable<string> filteredNames =
Enumerable.Where (names, n => n.Length >= 4);
Extension methods extend an existing type with new methods, without altering the type's definition. They act as syntactic sugar, making static methods feel like instance methods. Because LINQ's query operators are implemented as extension methods, we can simplify our preceding query as follows:
IEnumerable<string> filteredNames =
names.Where (n => n.Length >= 4);
Implicitly typed local variables let you omit the variable type in a declaration statement, allowing the compiler to infer it. Because the compiler can determine the type of filteredNames, we can further simplify our query:
var filteredNames = names.Where (n => n.Length == 4);
Query comprehension syntax provides SQL-style syntax for writing queries. Comprehension syntax can simplify certain kinds of queries substantially, as well as serving as syntactic sugar for lambda-style queries. Here's the previous example in comprehension syntax:
var filteredNames = from n in names
where n.Length >= 4
select n;
Anonymous types are simple classes created on the fly, and are commonly used in the final output of queries:
var query = from n in names where n.Length >= 4
select new {
Name = n,
Length = n.Length
};
Here's a simpler example:
var dude = new { Name = "Bob", Age = 20 };
Implicitly typed arrays eliminate the need to state the array type, when constructing and initializing an array in one step:
var dudes = new[]
{
new { Name = "Bob", Age = 20 },
new { Name = "Rob", Age = 30 }
};
Object initializers simplify object construction by allowing properties to be set inline after the constructor call. Object initializers work with both anonymous and named types. For example:
Bunny b1 = new Bunny {
Name = "Bo",
LikesCarrots = true,
};
The equivalent in C# 2.0 is:
Bunny b2 = new Bunny( );
b2.Name = "Bo";
b2.LikesCarrots = false;
Automatic properties cut the work in writing properties that simply get/set a private backing field. In the following example, the compiler automatically generates a private backing field for X:
public class Stock
{
public decimal X { get; set; }
}
Partial methods let an auto-generated partial class provide customizable hooks for manual authoring. LINQ to SQL makes use of partial methods for generated classes that map SQL tables.
Expression trees are miniature code DOMs that describe lambda expressions. The C# 3.0 compiler generates expression trees when a lambda expression is assigned to the special type Expression<TDelegate>:
Expression<Func<string,bool>> predicate =
s => s.Length > 10;
Expression trees make it possible for LINQ queries to execute remotely (e.g., on a database server) because they can be introspected and translated at runtime (e.g., into an SQL statement).
0 comments:
Post a Comment