// i is compiled as an int
var i = 5;
// s is compiled as a string
var s = "Hello";
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
// expr is compiled as IEnumerable
// or perhaps IQueryable
var expr =
from c in customers
where c.City == "London"
select c;
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
// list is compiled as List
var list = new List
. Anonymous types
C# 3.0 gives you the flexibility to create an instance of a class without having to write code for the class beforehand. So, you now can write code as shown below:
new {hair="black", skin="green", teethCount=64}
The preceding line of code, with the help of the "new" keyword, gives you a new type that has three properties: hair, skin, and teethCount. Behind the scenes, the C# compiler would create a class that looks as follows:
class __Anonymous1
{
private string _hair = "black";
private string _skin = "green";
private int _teeth = 64;
public string hair {get { return _hair; } set { _hair = value; }}
public string skin {get { return _skin; } set { _skin = value; }}
public int teeth {get { return _teeth; } set { _teeth = value; }}
}
. Extension methods
Extension methods enable you to extend various types with additional static methods. However, they are quite limited and should be used as a last resort—only where instance methods are insufficient.
Extension methods can be declared only in static classes and are identified by the keyword "this" as a modifier on the first parameter of the method. The following is an example of a valid extension method:
public static int ToInt32(this string s)
{
return Convert.ToInt32(s) ;
}
If the static class that contains the above method is imported using the "using" keyword, the ToInt32 method will appear in existing types (albeit in lower precedence to existing instance methods), and you will be able to compile and execute code that looks as follows:
string s = "1";
int i = s.ToInt32();
This allows you to take advantage of the extensible nature of various built-in or defined types and add newer methods to them.
. Object and collection initializers
public class CoOrdinate
{
public int x ;
public int y;
}
You then could declare and initialize a CoOrdinate object using an object initializer, like this:
var myCoOrd = new CoOrdinate{ x = 0, y= 0} ;
The above code may have made you raise your eyebrows and ask, "Why not just write the following:"
var myCoOrd = new CoOrdinate(0, 0) ;
Note: I never declared a constructor that accepted two parameters in my class. In fact, initializing the object using an object initializer essentially is equivalent to calling a parameterless (default) constructor of the CoOrdinate object and then assigning the relevant values.Similarly, you should easily be able to give values to Collections in a rather concise and compact manner in C# 3.0.For instance, the following C# 2.0 code:
List
animals.Add("monkey");
animals.Add("donkey");
animals.Add("cow");
animals.Add("dog");
animals.Add("cat");
Now can be shortened to simply:
List
"monkey", "donkey", "cow", "dog", "cat" } ;
. Lambda expressions
It Allowes you to write code blocks in methods, which you could invoke easily using delegates. Delegates are definitely useful, and they are used throughout the framework, but in many instances you had to declare a method or a class just to use one. Thus, to give you an easier and more concise way of writing code, C# 2.0 allowed you to replace standard calls to delegates with anonymous methods. The following code may have been written in .NET 1.1 or earlier:
class Program
{
delegate void DemoDelegate();
static void Main(string[] args)
{
DemoDelegate myDelegate = new DemoDelegate(SayHi);
myDelegate();
}
void SayHi()
{
Console.Writeline("Hiya!!") ;
}
}
In C# 2.0, using anonymous methods, you could rewrite the code as follows:
class Program
{
delegate void DemoDelegate();
static void Main(string[] args)
{
DemoDelegate myDelegate = delegate()
{
Console.Writeline("Hiya!!");
};
myDelegate();
}
}
Lambda expressions are simply functions and they are declared in the context of expressions than as a member of a class. It is an inline expression or a statement block which can be used to pass arguments to a method or assign value to delegate. All lambda expressions use the lambda operator => and the left side of the operator denotes the results and the right side contains the expression to be evaluated. For instance, consider the following lambda expression:
age => age + 1;
The above function takes one argument named age, and returns age + 1 as the result. As you can see, Lambda expressions follow the below syntax:
(parameter-list) => expression;
where expression can be any C# expression or a block of code. Just like anonymous methods you can use a lambda expression in place of a delegate. Here are some sample lambda expressions and their corresponding delegates.
//Explicitly typed parameter
(Person obj) => MessageBox.Show(obj.FirstName.ToUpper());
//Implicitly typed parameter
(obj) => obj.FirstName == "Thiru";
//Explicitly typed parameter
(int a, int b) => a + b
//Implicitly typed parameter
(x, y) => { return x + y; }
As you see from the preceding lines of code, lambda expressions can be written in such a way that itcan infer the parameter type from the signature of the delegate it is assigned to.
. Query expressions
Even though further enhancements may be introduced in the coming months as C# 3.0 matures, the new features described in the preceding sections make it a lot easier to work with data inside C# in general. This feature, also known as LINQ (Language Integrated Query), allows you to write SQL-like syntax in C#.
For instance, you may have a class that describes your data as follows:
public class CoOrdinate
{
public int x ;
public int y;
}
You now could easily declare the logical equivalent of a database table inside C# as follows:
// Use Object and collection initializers
List
And now that you have your data as a collection that implements IEnumerable
var filteredCoords =
from c in coords
where x == 1
select (c.x, c.y)
In the SQL-like syntax above, "from", "where", and "select" are query expressions that take advantage of C# 3.0 features such as anonymous types, extension methods, implicit typed local variables, and so forth. This way, you can leverage SQL-like syntax and work with disconnected data easily.
Each query expression is actually translated into a C#-like invocation behind the scenes. For instance, the following:
where x == 1
Translates to this:
coords.where(c => c.x == 1)
As you can see, the above looks an awful lot like a lambda expression and extension method. C# 3.0 has many other query expressions and rules that surround them.
. Expression Trees
Expression trees represent language-level code in the form of data. The data is stored in a tree-shaped structure. Each node in the expression tree represents an expression, for example a method call or a binary operation such as
x <>
param.Name, left.Name, operation.NodeType, right.Value);
/* This code produces the following output:
Decomposed expression: num => num LessThan 5
*/
. Implicitly typed arrays.
class ImplicitlyTypedArraySample
{
static void Main()
{
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { "hello", null, "world" }; // string[]
// single-dimension jagged array
var c = new[]
{
new[]{1,2,3,4},
new[]{5,6,7,8}
};
// jagged array of strings
var d = new[]
{
new[]{"Luca", "Mads", "Luke", "Dinesh"},
new[]{"Karen", "Suma", "Frances"}
};
}
}
No comments:
Post a Comment