New Features of C# 3.0 :-
- Anonymous Types
- Extension Methods
- Object Initializers
- Collection Initializers
- Implicitly typed local Variable
- Lambda Expressions
- Expression Trees
- Linq Query Expression pattern
- Auto-Implement Properties
- Partial Methods
Anonymous types in C# 3.0
- Anonymous types are particularly useful when querying and transforming data with LINQ.
- You create anonymous types by using the new operator together with an object initializer.
- Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence.
- Anonymous types contain one or more public read-only properties. No other kinds of class members, such as methods or events, are valid.
- The most common scenario is to initialize an anonymous type with properties from another type.
- If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them. You must provide a name for a property that is being initialized with an expression.
class TheCar
private string make;
public string Make
{
get
{ return make; }
Set
{make = value; }
}
Private string model;
Public string Model
{
get { return model; }
Set { model = value; }
}
}
To create an instance of this class and set the properties we would write
TheCar mycar = new
TheCar ();
mycar.Make = “Fiat”;
mycar.Model = “Fiat Punto”;
Using the object initialization syntax we can write the following statementvar mycar=new TheCar{Make=”Fiat”,Model=”Fiat punto”};
With anonymous types I would rewrite the statement above to this
var mycar=new {Make=”Fiat”,Model=”Fiat punto”};
Remarks:
- Anonymous types are class types that derive directly from object, and that cannot be cast to any type except object. The compiler provides a name for each anonymous type, although your application cannot access it.
- If two or more anonymous types in the same assembly have the same number and type of properties, in the same order, the compiler treats them as the same type. They share the same compiler-generated type information.
- You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type.
- you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type.
- To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type object.
- Extension Methods:
- Extension methods allow you to easily extend a type, such as an
integer
orstring
, without re-compiling or modifying the type. In essence, they are a type ofstatic
(shared
in VB) method, but they are called as if the method is native to the type. Extension methods are available from the 3.5 version of the .NET Framework and can be implemented on any type in the .NET Framework or any custom type that you define. - You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called.
- One downside to extension methods is if that you create an extension method with the same name as another method in that type, the compiler will bind the method call to the native method, not any extension. An extension method is only called when there is no native method found.
- Remember the following two points while implementing extension methods for a given type:
- An extension method will never be called if it has the same signature as a method defined in the type.
- Extension methods are brought into scope at the namespace level. For example, if you have multiple static classes that contain extension methods in a single namespace named Extensions, they will all be brought into scope by the using Extensions; directive.
How Do We Create Extension Methods?
The basic outline of creating
extension methods goes something like this:
- Create a public static class (module in VB)
- Define functions that you wish to perform
- Make the functions an extension method
public static class Extensions
{
}
The
next phase would be to write the function that we are going to need, which in
this case is the following:
public static class Extensions
{
public string GetFirstThreeCharacters(String str)
{
if(str.Length < 3)
{
return str;
}
else
{
return str.Substring(0,3);
}
}
}
To make our C# version of
our function, we need an extension method
to mark the function as
static
(so
that it can be accessed at any time without the need for declaring anything)
and secondly, mark the first parameter with the this
keyword. This keyword basically tells the CLR
that when this extension method is called,
to use "this
" parameter
as the source. See the following:public static class Extensions
{
String str = "my new String";
str = str.GetFirstThreeCharacters();
public static string GetFirstThreeCharacters(this String str)
{
if(str.Length < 3)
{
return str;
}
else
{
return str.Substring(0,3);
}
}
}
Benefits of extension
methods
- Extension methods allow existing classes to be extended without relying on inheritance or having to change the class's source code.
- If the class is sealed than there in no concept of extending its functionality. For this a new concept is introduced i.e. extension methods.
- This feature is important for all developers especially if you would like to use the dynamism of the C# enhancements to be taken place in your classes design.
Example:
using System;
using System.Text;
namespace ExtensionMethod2
{
public static class ExtMetClass
{
public static int IntegerExtension(this string str)
{
return Int32.Parse(str);
}
}
class Program
{
static void Main(string[] args)
{
string str = "123456";
int num = str.IntegerExtension();
Console.WriteLine("The output using extension method: {0}", num);
Console.ReadLine();
}
}
}
In the above program we have used extension method IntegerExtension() to convert string to numeric type
Important points while using extension methods:
using System;
using System.Text;
namespace ExtensionMethod2
{
public static class ExtMetClass
{
public static int IntegerExtension(this string str)
{
return Int32.Parse(str);
}
}
class Program
{
static void Main(string[] args)
{
string str = "123456";
int num = str.IntegerExtension();
Console.WriteLine("The output using extension method: {0}", num);
Console.ReadLine();
}
}
}
In the above program we have used extension method IntegerExtension() to convert string to numeric type
Important points while using extension methods:
- An extension method must be defined in a top-level static class.
- An extension method with the same name and signature as an instance method will not be called.
- Extension methods cannot be used to override existing methods.
- The concept of extension methods cannot be applied to fields, properties or events.
- Overuse of extension methods is not good style of programming.
Object Initializers:
Object Initializers let you
assign values to any accessible fields or properties of an object at creation time
without having to explicitly invoke a constructor.
The following example shows
how to use an object initializer with a named type, Cat.
Note the use of auto-implemented properties in the Cat
class
Examples
class Cat
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Object Initializers with Anonymous types:
var pet = new { Age = 10, Name = "Fluffy" };
Anonymous types enable the select clause in a LINQ query expression to transform
objects of the original sequence into objects whose value and shape may differ
from the original.
var productInfos =
from p in products
select new { p.ProductName, p.UnitPrice };
It is a compile-time error
to use a collection initializer with a nullable struct.
Collection Initializers
- Collection initializer gives a simple syntax to create instance of a collection.
- Any object that is implementing System.Collections.Generic.ICollection<T>can be initialized with collection initializer.
Let us say, we have a class Student.cs
public class Student
{
public string
FirstName { get; set;
}
public string
LastName { get; set;
}
}
Now if we want
to make collection of this class and add items of type student in that
collection and retrieve through the collection, we need to write below code
Program.cs
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
List<Student> lstStudent = new
List<Student>();
Student std = new Student();
std.FirstName = "Dhananjay";
std.LastName = "Kumar ";
lstStudent.Add(std);
std = new Student();
std.FirstName = "Mritunjay ";
std.LastName = "Kumar";
lstStudent.Add(std);
foreach (Student
resstd in lstStudent)
{
Console.WriteLine(resstd.FirstName);
}
Console.Read();
}
}
}
Implicitly Types Local Variable:
Implicitly typed local
variable can be defined with VAR keyword. The var
keyword instructs the compiler to infer the type of the variable from the
expression on the right side of the initialization statement.The inferred type
may be a built-in type, an anonymous type, a user-defined type, or a type
defined in the .NET Framework class library.
// 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<Customer>
// or perhaps IQueryable<Customer>
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<int>
var list = new List<int>();
Lambda Expressions:
A lambda expression
is an anonymous function that can contain expressions and statements, and can
be used to create delegates or expression tree types.
- All lambda expressions use the lambda operator =>, which is read as "goes to".
- The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block.
- The lambda expression x => x * x is read "x goes to x times x." This expression can be assigned to a delegate type as follows:
Example:
delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
To create an expression tree
type:using System.Linq.Expressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Expression<del> myET = x => x * x;
}
}
}
A lambda expression with an expression on the right side is called an expression lambda. Expression lambdas are used extensively in the construction of Expression Trees
(input parameters) => expression
The
parentheses are optional only if the lambda has one input parameter; otherwise
they are required. Two or more input parameters are separated by commas enclosed
in parentheses: (x, y) => x == y
Sometimes it is difficult or impossible for the compiler
to infer the input types. When this occurs, you can specify the types
explicitly as shown in the following example:
(int x, string s) => s.Length > x
How to: Use Lambda Expressions in a Query
Example:
class SimpleLambda
{
static void Main()
{
// Data source.
int[] scores = { 90, 71, 82, 93, 75, 82 };
// The call to Count forces iteration of the source
int highScoreCount = scores.Where(n => n > 80).Count();
Console.WriteLine ("{0} scores are greater than 80", highScoreCount);
// Outputs: 4 scores are greater than 80
}
}
The above example demonstrates how to use a lambda expression in a method-based query by using the Enumerable. Where standard query operator.
Note that the Where method in this example has an input parameter of the delegate type Func(Of TResult) and that delegate takes an integer as input and returns a Boolean.
The lambda expression can be converted to that delegate
Expression Trees
Expression trees represent
code in a tree-like data structure, where each node is an expression, for
example, a method call or a binary operation such as x < y.
Expression trees are also
used in the dynamic language runtime (DLR) to provide interoperability between
dynamic languages and the .NET Framework and to enable compiler writers to emit
expression trees instead of Microsoft intermediate language (MSIL).
create an expression tree
that represents the lambda expression num => num < 5
(C#)
Example:
Expression<Func<int, bool>> lambda = num => num < 5;
LINQ Query Expression:
- Query expressions can be used to query and to transform data from any LINQ-enabled data source. For example, a single query can retrieve data from a SQL database, and produce an XML stream as output.
- Query expressions are easy to master because they use many familiar C# language constructs.
- The variables in a query expression are all strongly typed, although in many cases you do not have to provide the type explicitly because the compiler can infer it.
- A query is not executed until you iterate over the query variable in a Foreach statement. For more information,
- At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C# specification. Any query that can be expressed by using query syntax can also be expressed by using method syntax. However, in most cases query syntax is more readable and concise.
Examples:
class LINQQueryExpressions
{
static void Main()
{
// Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 };
// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
// Output: 97 92 81
Automatic Properties:
Previously we used to define
Properties the following way.
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
According to Automatic
Properties we can define the properties in the following way.
public string Name
{
get;
set;
}
Partial Methods:
1.
Partial method declarations must begin partial keyword.
2. The return type of a partial method must be void.
3. Partial methods can have ref but not out parameters.
4. Partial methods are implicitly private, and therefore they cannot be virtual.
5. Partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing.
2. The return type of a partial method must be void.
3. Partial methods can have ref but not out parameters.
4. Partial methods are implicitly private, and therefore they cannot be virtual.
5. Partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing.
To create a partial method we
create the declaration of the method in one part of the partial class and
implementation in the other part of the partial class. The implementation is
optional. If the implementation is not provided, then the method and all the
calls to the method are removed at compile time.
Therefore, any code in the
partial class can freely use a partial method, even if the implementation is
not supplied. No compile-time or run-time errors will result if the method is
called but not implemented.
In summary a partial method
declaration consists of two parts.
The definition, and the implementation.
These may be in separate parts of a partial class, or in the same part. If
there is no implementation declaration, then the compiler optimizes away both
the defining declaration and all calls to the method.
Advantages
of partial methods
Partial methods can
be used to customize generated code. They allow for a method name and signature
to be reserved, so that generated code can call the method but the developer
can decide whether to implement the method. Much like partial classes, partial
methods enable code created by a code generator and code created by a human
developer to work together without run-time costs.
Partial Methods Example:
public partial class CustomTypedCollection
{
partial void BeforeAddingElement(CustomElement element);
public void AddElement(CustomElement element)
{
BeforeAddingElement();
}
}
public partial class CustomTypedCollection
{
partial void BeforeAddingElement(CustomElement element)
{
Console.WriteLine("Element " + element + " is being added.");
}
}
class Program
{
static void Main(string[] args)
{
CustomTypedCollection c = new CustomTypedCollection();
c.AddElemeent(new CustomElement());
}
}
No comments :
Post a Comment