
Apress Introducing Dot Net 4 With Visual Studio_8
Mô tả tài liệu
Tham khảo tài liệu 'apress introducing dot net 4 with visual studio_8', công nghệ thông tin, hệ điều hành phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả
Tóm tắt nội dung
Using extension methods, operation chaining becomes a more natural could not have done in the C# 2.0 days using plain static methods and anonymous by a squaring and the end result is a type that method, similar to that takes a predicate delegate as a parameter and uses it to
This class provides a whole host of extension methods that
All these extension methods operate on types
Also, the class provides the same extension methods for types methods offer even more to create custom iterators
for in a very that don’t support as I’ll show in the next section, from Let’s look at how you can use extension methods to implement custom iterators on
types example, imagine a matrix as a type.
var matrix = new {
new List<int> { 1, 2, 3 },
new List<int> { 4, 5, 6 },
new List<int> { 7, 8, 9 }
using an extension method:
var matrix = new {
new List<int> { 1, 2, 3 },
new List<int> { 4, 5, 6 },
new List<int> { 7, 8, 9 }
In this version, I have the iteration into the extension the same time, I made the extension method generic so it will accept nested lists
You might have already noticed that many of the new features added in C# 3.0 a
You’ve always been able to implement models in C#, but
the new language features make it easier by making the language more Caution Although I have named this type IList<T> for this example, be sure not to confuse it with IList<T> in
In the following example code, I create a custom list called MyList<T> that static IList<T> items ) {
public static IList<T> iter ) {
var listInts = new List<int> { 1, 2, 3, 4 }; static method populates using these in Main uses this iterator to send all the list items to the the example, notice that the method creates a forward iterator by making
Check out the following revised version of the iterator extension method and the Main method:
var listInts = new List<int> { 1, 2, 3, 4 };
var iterator = delegate( list ) { list ) {
Notice that the method accepts two more one of which is then called
Main method, I am passing two delegates in the form of anonymous method can be used to iterate over every other item in the list simply by modifying
■ Note Some of you might already be familiar with lambda which were in C# 3.0.
when using lambda you can clean up this code by using the lambda syntax
I cover lambda in Chapter 15.
As a final extension method example for on the IList<T> type, consider how we could
create an extension method to reverse the list and return a new along the way.3 In the preceding code, the anonymous method is assigned to the
In a way, the anonymous method captures initiates the chain of recursive calls to the anonymous method and then passes
the resulting List<T> to the method, thus creating the reversed the temporary List<T> entirely and build the new MyList<T> using a captured variable as
The previous method first creates an anonymous function and stores it in the local
It then returns the results of calling the anonymous method to the caller of method and the captured local variables and itself until it is finished building the reversed list into the captured extension method can be cleaned up by the captured variable and
the method uses only the stack as a temporary storage location while building the new = list, IList<T> result) {
return new result) );
■ Note This code uses the Func<> which is a generic delegate that is defined in the System
Using Func<> is a shortcut you can employ to avoid having to declare delegate types all over the
You use the Func<> type parameter list to declare what the parameter types (if any) and return type of the
If the delegate you need has no return value, you can use the Action<> generic delegate type.
The MyList<T> class used in the previous examples builds the linked list from the
type entirely before the MyList<T> object can be used.
If you are creating a library for general use that contains a type such as
For example, consider a of types that might or might not be related by and
way to do it is to introduce a new base type that derives from Validate as an
abstract method, and then makes all the other types derive from the new type instead of a of unrelated types, you will probably implement a host of extension static class
public static void Validate( this Employee emp ) {
public class Employee
Notice that for each type of object we want to validate (in this example there are three), I have
defined a separate Validate extension method is being called for each instance and is as follows:
In this example, it’s important to note that the visitors, in this case the extension methods named
■ Note Keep in mind that if the extension methods are defined in the same assembly as the types they are
form of the Validate extension method that can be used if the instance supports a Validate method that will be called if the type the static class
public static void Validate( this Employee emp ) { "Instance of following type" +
public class Employee
not a version of Validate that takes the type as its first the generic form of
Validate will be called, which then passes through to the method on the that I removed the extension method whose first parameter was of type so
method to generic forms of the extension method that accept one generic type you how they can be used to create useful things such as iterators types) on
Even for types that do have you can define
lambda extension methods provide a certain degree of that is extremely
While showing how to create custom I took a slight detour (using anonymous functions
rather than lambda to show you the world of that the features
The code for those examples will become much cleaner when you use lambda instead of anonymous the next chapter, I’ll introduce you to lambda which really make into either code or data in the form of IL code or an tree,
Most of the new features of C# 3.0 opened up a world of to the C# language, and one can use and implement in
C# 3.0 the language into a more hybrid language in which both and
Lambda are arguably the to Lambda
Using lambda you can define function objects for use at any this via whereby you create a function object (in the form of a delegate)
Lambda join these two and one statement in the that takes functions in its parameter list and operates on those possibly even
Lambda provide
In simple syntactic terms, lambda are a syntax whereby you can declare anonymous in a more fluid and way.
Just about every use of an anonymous method can be replaced with a lambda
CHAPTER 15 ■ LAMBDA first, the syntax of lambda might take some time to get used when you are looking at a lambda all by really take two lambda are a direct for anonymous on
Both types of lambda can be converted
However, lambda without statement blocks offer something truly can convert them into trees based on the types in the
creating trees from lambda in the section titled Trees” later in this
Lambda and Closures
First, let’s look at the simpler form of lambda that is, the ones without a statement in the previous section, a lambda is a shorthand way of declaring a simple
The following lambda can be used as a delegate that accepts one
What this says is “take x as a parameter and return the result of following operation on x.” Notice that the
lambda is devoid of any type the compiler will deduce the type of the argument x and the type of the result depending on the
It means that if you are assigning a lambda to a delegate, the types of
the delegate are used to determine the types within the lambda shows what happens when a lambda is assigned to a delegate type:
I have marked the lambda in bold so that it stands out.
3 I covered some examples of with anonymous methods in Chapter 15 ■ LAMBDA
When the compiler assigns the lambda to the expr variable, it
uses the type of the delegate to determine that the type of x must be int, and the type of the
You can fix this by different types in the delegate as shown here:
For the sake of this lambda has what’s called an typed list, and in this case, x is declared as type parameter list in a lambda and assign it to a delegate, the argument types
■ Note When using typed parameter lists, notice that the parameter list must be enclosed in of only one typed the lambda is assigned to a delegate, the return type of the is generally
So, in the following code the return type of the
is double because the inferred type of the parameter x is double:
error CS1662: Cannot convert 'lambda to
delegate type because some of the return
CHAPTER 15 ■ LAMBDA
types in the block are not to the delegate return
type
You can “fix” this by casting the result of the lambda body to int:
■ Note Explicit types in lambda parameter lists are required if the delegate you are assigning them to
One could argue that fixing the parameter types within a lambda
Now I want to show you a simple lambda that accepts no
Notice how simple it was to pass a function as a parameter into the method using this
lambda I want to show you an example of a lambda that accepts more than one
CHAPTER 15 ■ LAMBDA
var = new {
In this case, the lambda is used to create a delegate that accepts two of type
As you can see, lambda provide a nice, succinct way of creating
how to use lambda as to create flexible delegate int
CHAPTER 15 ■ LAMBDA
Look at all the work involved without lambda this case, the is a pointer to the counter variable in the Main of the code cannot be verified by the CLR.4 Then, in the Main method, I created an instance of
CHAPTER 15 ■ LAMBDA
public field of the generated class that the closure with a reference to the captured variable or a copy
if the captured variable is a value an instance of it in C# code because the name itself, if typed in code, will generate a syntax error.
In C# 2.0, anonymous methods were to reduce the burden I just not as as lambda because they still carry the old style with them and require parameter types in the parameter would be using anonymous methods, so you can see the in syntax
from lambda
I have bolded the between this example and the original lambda still not as and succinct as the lambda lambda you
CHAPTER 15 ■ LAMBDA
■ Note In the previous code example, you likely noticed the of the counter variable
within the lambda Variable I described how you can do the same thing with anonymous essence, any time a lambda the
All the lambda I have shown so far have been purely of the type of
lambda is one I like to call a lambda is similar in form to the lambda shown in the previous section can be converted to a lambda with a statement block simply
by the with curly braces after prefixing the right side with a return example, the following lambda
In form, lambdas with statement blocks are almost identical to anonymous major between lambdas with statement blocks and lambda blocks can be converted only to delegate types, whereas lambda can be converted
both to delegates and to trees typed by the family of types centered around Note The big between lambdas with statement blocks and anonymous methods is that anonymous
methods must type their whereas the compiler can infer the types of the lambda based on
The syntax offered by lambda fosters a more Trees
So far, I have shown you lambda that replace the of lambda into trees based on the types in the
CHAPTER 15 ■ LAMBDA
you’ve already seen how you can convert a lambda into a delegate as shown here:
In this line of code, the is converted into a delegate that accepts a single int parameter int>> expr = n => n+1;
The lambda instead of being converted into a callable delegate, is
The type of the expr variable is where T is replaced with the type of delegate the lambda can be converted notices that you are trying to convert the lambda into an instance and generates all the code to make it later in time, you can then compile the into a usable delegate as shown in the next
using int>> expr = n => n+1;
The line in bold shows the step at which the is compiled into a multiple trees to create more complex trees prior to compiling them.
One could even define a new language or implement a parser for an already existing fact, the compiler acts as an parser when you assign a lambda into an type tree and if you use ILDASM or Reflector to look at the generated code, you can see it in
The previous example could be rewritten without using the lambda as follows:
using
var n = "n" );
CHAPTER 15 ■ LAMBDA
var expr =
assigned the lambda n => this longhand example helps express the true of of the lambda n = "n" );
■ Note In these examples, I am using typed variables to save myself a lot of typing and to reduce clutter the variables are still strongly line of code says that we need an to represent a variable named n that is of type that in a plain lambda this type can be inferred based upon the delegate type the number 1, to an the parameter of building block of trees, using the new operator along with the of the type.
The is not so you must use the static methods on the class to create to decide which type we really 15 ■ LAMBDA you will notice that there are no public on these types.
of derived types using the type, which the factory pattern and exposes static
methods for creating instances of derived that you have the you need to use the method to bind
the (in this case, n+1) with the in the parameter list (in this case, n).
the example I use the generic Lambda<> method so that I can create the type more point I want to make that how represent as data is
expr variable, you will notice that in either the “Autos” or “Locals” windows, the is parsed and trees.
■ Note If I had used the version of the method, the result would have been an
instance of rather than however, instead of a strongly typed delegate, it returns an instance of type the Delegate instance, you must cast it to the specific delegate type; in this case, Func<int, int> or
could throw an exception at run time if you have a mismatch between your and the type of delegate on
Now I want to show you an example of how you can take an tree generated from a lambda and modify it to create a new tree.
In this case, I will take the (n+1) and
using expr = n => n+1;
CHAPTER 15 ■ LAMBDA
// by 2.
expr = ),
The bolded lines show the stage at which I multiply the original lambda by to notice that the passed into the Lambda<> method (the second need
to be exactly the same instances of the that come from the original that is,
Lambda<> method; at run time you will receive an exception similar to the following because
There are many classes derived from the class and many static methods for creating of them and combining other namespace for all the fantastic trees and how Lisp and similar languages represent functions as data you might already guess, within the scope of C#, trees are extremely useful when
most important fact is that LINQ provides a syntax for to search a large in-memory array (or any other type) for items that match a
LINQ is and can provide a means of operating on other types of stores, such on any type that supports 15 ■ LAMBDA
LINQ might be.
If the LINQ is in data (as an tree) rather than in IL (as a
Or maybe when your analyzes the
data, you can translate the tree into the final operation via a mechanism such as
Had the only been available as IL code from
power of trees in of Lambda
Now that I have shown you what lambda look like, let’s consider some of the things you can
You can actually implement most of the following examples in C# using anonymous
methods or I want to how you can use lambda to create custom want to show how you can iterate over a generic type that might or might not be a in the from the custom iterator creation method, including the type of the item stored, the type of
CHAPTER 15 ■ LAMBDA is the type of the which in this
example is specified as at the point of is the type that the code returns via the yield are delegate types that it uses to determine how to iterate over the 15 ■ LAMBDA
First, it needs a way to access the current item in the which, for this example, is expressed
in the following lambda which uses the values within the cursor array to index the item
supply the following lambda that just checks to see whether the cursor has stepped off of the
lambda which simply advances both of the cursor:
Other of could accept a first parameter of type given to access the current each value by 2 in the lambda that accesses the current item in the
lambda syntax to C# opens one’s eyes to the 15 ■ LAMBDA
CHAPTER 15 ■ LAMBDA
concept in many ways, even creating a random number generator using C# variable delta and the delegate func embody the the captured variable is to both the delegate and the context the lambda it means that the captured variable can be changed outside the scope and out of band of the
In essence, two methods (Main and the delegate) both have access to 15 ■ LAMBDA
■ Note In reality, when a closure is formed, the C# compiler takes all those variables and wraps them up in a
It also the delegate as a method of the is that the function itself is treated as a object that can be and
You’ve already seen how lambda can be converted into trees so you can operate on them, producing more or less complex a quick example of what I mean, consider two lambda
You could create a method to combine such lambda to create a compound lambda
the Main method, you can see how I used it to produce the compound after calling Chain<> is to the delegate you get when you convert the following lambda into a delegate:
Having a method to chain arbitrary like this is useful indeed, but let’s look at other ways
CHAPTER 15 ■ LAMBDA
But instead of modifying the original let’s look at how to create a method that
accepts the original delegate as a parameter and returns a new delegate to replace the has no entropy, meaning that for the same input it always returns the same set has already been computed and return it rather than calling the 15 ■ LAMBDA
public static class Memoizers method to the delegate to produce a new Memoize<> method wraps the original delegate that’s
CHAPTER 15 ■ LAMBDA
CHAPTER 15 ■ LAMBDA
For that matter, many more useful things can be done with methods that accept functions and
In the previous section on closures I how to create a method that accepts a function, given
as a delegate, and produces a new of In short, what it means is creating an operation (usually a method) that accepts
Suppose that you have a lambda that looks like the
Now, suppose that you have a list of doubles and you want to use this lambda to add a
constant value to each item on the list, producing a new based on the original lambda in which one of the variables is forced to a static 15 ■ LAMBDA
var mylist = new { 1.0, 3.4, 5.4, 6.54 };
// Here is the original meat of this example is in the Bind2nd<> extension method, which I have it creates a closure and returns a new delegate that accepts only one delegate is called, it passes its only parameter as the first parameter to the original delegate and
var mylist = new { 1.0, 3.4, 5.4, 6.54 };
CHAPTER 15 ■ LAMBDA
// Here is the original original function to) and returns another delegate that is the curried which fact is assigned the lambda for the factorial captures the fact delegate
Remember that even though a closure captures a variable for use inside the anonymous method,
which is here as a lambda the captured variable is still and mutable
from outside the context of the capturing anonymous method or lambda 15 ■ LAMBDA
We fact to reference a new delegate based on the lambda
But still the lambda (x) => x > 1 the new (x) => x+1, which is different behavior from the recursion you had the captured variable (the func delegate) are several ways to fix this problem, but the typical method is to use anonymous
What ends up happening is that you modify the preceding factorial lambda to accept another
and converts the captured variable into a parameter to the that is passed on the stack (in this case, the parameter f in the fact this chapter, I you to the syntax of lambda which are, for the most part,
In fact, it’s a shame that lambda did not come along
with C# 2.0 because then there would have been no need for anonymous convert lambda with and without statement bodies, into how lambda without statement bodies are to trees based on the type as defined in the trees, you
can apply to the tree before actually compiling it into a delegate and calling
CHAPTER 15 ■ LAMBDA
I finished the chapter by showing you useful of lambda by using closures, delegate parameter binding using
2.0 using anonymous methods, the of lambda syntax to the language makes using such
and of we have features like lambda anonymous types, extension
methods, and typed
At first glance, LINQ query look a lot like SQL all, C# is a strongly typed language, and so is
The language adds several new keywords for building query query typically get into a chain of extension method calls on a sequence or is clearly defined, and they are called standard query the compiler merely query into a series of method calls, it follows that you can provide your own of those extension example, the class provides of those
methods for LINQ to Objects, whereas provides of those methods for
querying types that implement and are commonly used with LINQ to I create a of Employee objects and then perform a simple query:
public class Employee
var employees = new {
titled “Standard Query In this example, I marked the query in bold to make it
It’s quite shocking if it’s the first time you have seen a LINQ SQL, the select clause is normally the beginning of the to the query I created a simple list of Employee instances just to have some data to
Each query starts off with a from clause, which declares what’s called a range from clause in our example is very similar to a foreach statement in that it iterates over the employees and stores each item in the in the variable employee during each the closes with select, which is a perform a in the query you are typically creating another of
Another thing to note is my use of anonymous types in the select prior to my query and made my select clause instances of that type, but doing so
defeats some of the and of the LINQ does not execute at the point the query variable is and the use of foreach on the query variable produces
The end result of building the query in what’s called a query variable, which
Notice that I reference it using an typed what the type of query Methods and Lambda Revisited
Before I break down the elements of a LINQ in more detail, I want to show you an alternate the compiler simply the LINQ into a series of extension method
calls that accept lambda usable on types, whereas Queryable defines the same of generic methods usable on see they have names just like the clauses in query methods implement the standard query operators I mentioned in the previous query in the previous example can be replaced with the following code:
Notice that it is simply a chain of extension method calls on which is by method syntax and simply call them as static methods, as shown here:
methods could even go one step further and replace the lambda with anonymous to say, the and Queryable extension methods are very useful even outside the
And as a matter of fact, some of the provided by the extension methods
LINQ is built upon the use of standard query which are methods that operate on sequences
compiler a query it typically converts the into a series or chain of calls
to those extension methods that implement the query by calling the extension methods as code with query extension methods, and a complete query might be extension methods, and the compiler will generate calls to them while compiling a LINQ query finding the extension methods in I provide my own of the standard query operators Where and Select that simply you cannot use a LINQ query because the from clause requires a data source
C# 2008 a small set of new keywords for creating LINQ query some of which we
which is a local variable of sorts used to represent each item of the input as the query is applied to it.
A query might contain more than one from that LINQ are compiled into strongly typed code.
The compiler infers the types of those two range variables based
upon the type argument of the interface returned by Range returns a type
of the type of x and y is int.
to apply a query to a that only supports the cases, you must specify the type of the range variable, as shown here:
var query = from int n in numbers
You can see where I am typing the range variable n to type typed languages such as C# rely
upon the compiler to verify the integrity of the you perform on the types defined within the if there is a type-
var employees = new {
In the query I have the join building the result and projects that data into an anonymous your query contains a join the compiler converts it to a Join extension method call
the GroupJoin extension method which also groups the consist of the where keyword followed by a predicate is into a call to the Where extension method, and the predicate is passed to the Where
method as a lambda an type, convert the lambda into a the lambda into an tree.2 I’ll have more to say about trees in
public class Employee
var employees = new {
2 In Chapter 15, I show how lambda that are assigned to delegate instance variables are converted into IL code, whereas lambda that are assigned to are converted into
trees, thus the with data rather than that because the select clause simply returns the range variable, this whole query is nothing more than a sort example, I sort first by in ascending order, then the second in the orderby
clause sorts the results of each group by LastName in order, and then each of
At compile time, the compiler the first in the orderby clause into a call to the
OrderBy standard query operator extension a LINQ query, the select clause is used to produce the end result of the any filtering where clauses in the query they must precede the select converts the select clause into a call to the Select extension is converted into a lambda that is passed into the Select method, which uses it to types feature was born from the select operation during the of LINQ.
why anonymous types are so handy in this case, consider the following example:
public class Result
However, notice that I had to declare a new type Result just to hold the results of the
use anonymous types as follows:
I can go and add a new property to the result type and call it Output2, for
example, and it would not force any changes on anything other than the anonymous type
inside the query code will continue to work, and anyone who wants to use the new
Of course, there are some where you do want to use types in the select
clause such as when one of those type instances has to be returned from a of it as a local variable that is visible only within the query just as a local
public class Employee
var employees = new { you can use the variable as input to another from clause to create a new derived range
In the previous section titled “The from Clause and Range I gave an example using
The query can have an optional group clause, which is very powerful at the input
As you can see, this simple query iterated over all the items from the source data
In order to perform such a grouping, you can use an anonymous type to introduce the multiple keys into
public class Employee
Notice the anonymous type within the group how it works is that for each item, it builds an instance of the anonymous type and
If not, a new group is created with that instance of the anonymous type as the an into clause, you tell the query that you want to assign the results of a group or a join
C# Is a Strongly Typed and and Typed Local new with Value new with Class Parameter Define of Side Effects of Value Types Interface with Value and Formats of of String in Custom Types, and That Produce Anonymous and Methods as Delegate Parameter Value and Operators within Generic Types for Reference Type-Safe Forms of Interface Members and Derived Does the Compiler Find Extension a Type’s Contract Can Break Extension to Lambda and on of Lambda Methods and Lambda Typing in C#