|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn the previous article, I illustrated some of the C# 3.0 new language and compiler features. I'll illustrate the rest of the features in this second part.
In this article, I will define the last five features and provide code samples. Anonymous TypesThe C# compiler enables you to create a new type at runtime which is not available at the source code level. It encapsulates a set of read-only properties into a single object without having to first explicitly define a type. The type of the properties is inferred by the compiler which can create an anonymous type by using the properties in an object initializer. For example, consider the following declaration: var person = new { Name = "Mony Hamza", SSN = "12345678" };
Here, the compiler automatically creates an anonymous type and infers the types of the properties from the object initializer. It also creates the Here is an example for declaring an anonymous type and displaying its content: class MyClass
{
static void Main(string[] args)
{
// Declare an anonymous type:
var obj1 = new { Name = "Mony Hamza", SSN ="12345678" };
// Display the contents:
Console.WriteLine("Name: {0}\nSSN: {1}", obj1.Name,obj1.SSN);
Console.ReadLine();
}
}
Output: Name: Mony Hamza
SSN: 12345678
I've received a question about why to use "implicitly typed variables". If you are to use an anonymous variable, then this variable must be initialized using the keyword
Lambda ExpressionsLambda expressions provide a concise syntax for writing anonymous methods that can contain expressions and statements, and can be used to create delegates. All lambda expressions use the lambda operator Using Anonymous Methods in C# 2.0public delegate int MyDelegate(int n);
class AnonymouseMethods
{
static void Main()
{
// Anonymous method that returns the argument multiplied by 10:
MyDelegate delegObject1 = new MyDelegate(
delegate(int n) { return n * 10; }
);
// Display the result:
Console.WriteLine("The value is: {0}", delegObject1(5));
}
}
Using Lambda Expressions in C# 3.0public delegate int MyDelegate(int n);
class LambdaExpresion
{
static void Main()
{
// Anonymous method that returns the argument multiplied by 10:
MyDelegate Obj1= new MyDelegate(
delegate(int n) { return n * 10; }
);
// Display the result:
Console.WriteLine("The value using an anonymous method is: {0}",
Obj1(5));
// Using lambda expression to do the same job:
MyDelegate Obj2 = (int n) => n * 10;
// or:
// MyDelegate Obj2 = n => n * 10;
// Display the result:
Console.WriteLine("The value using a lambda expression is: {0}",
Obj2(5));
Console.ReadLine();
}
}
Output: The value using an anonymous method is: 50
The value using a lambda expression is: 50
We also can use more than one parameter in a lambda expression: public delegate int MyDelegate(int m, int n);
MyDelegate myDelegate = (x, y) => x * y;
Console.WriteLine("The product is: {0}", myDelegate(5, 4));
More ExamplesThe following example shows you how to select the number which when divided by two has a remainder of 1. int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
The following examples illustrate how to select the List < string > Names=new List < string >{"Mony","John","Liza"};
List < string > Filterd=Names.FindAll(name =>name.StartsWith("M"));
foreach(string i in Filterd)
{
Console.WriteLine(i);
}
Query KeywordsKeywords:
To understand Query expressions well, examples are the perfect choice. The following example illustrates how to select numbers less than 5 and when divided by two have a remainder of 0. static void Main()
{
// A simple data source.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// Create the query.
// lowNums is an IEnumerable < int >
var lowNums = from num in numbers
where num < 5 && num % 2 == 0
select num;
// Execute the query.
foreach (int i in lowNums)
{
Console.Write(i + " ");
}
}
The following example is from MSDN which will select all the students and their scores greater than 90, in order to access the inner list of scores. We use compound public class Student
{
public string LastName { get; set; }
public List < int > Scores {get; set;}
}
static void Main()
{
// Use a collection initializer to create the data source. Note that
// each element in the list contains an inner sequence of scores.
List < Student> students = new List < Student>
{
new Student {LastName="Omelchenko", Scores= new List < int> {97, 72, 81, 60}},
new Student {LastName="O'Donnell", Scores= new List < int> {75, 84, 91, 39}},
new Student {LastName="Mortensen", Scores= new List < int> {88, 94, 65, 85}},
new Student {LastName="Garcia", Scores= new List < int> {97, 89, 85, 82}},
new Student {LastName="Beebe", Scores= new List < int> {35, 72, 91, 70}}
};
// Use a compound from to access the inner sequence within each element.
// Note the similarity to a nested foreach statement.
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
// Execute the queries.
Console.WriteLine("scoreQuery:");
foreach (var student in scoreQuery)
{
Console.WriteLine("{0} Score: {1}", student.Last, student.score);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Output: scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
Perform Joins (this example is also from MSDN which shows how to perform cross join with and without conditions). static void Main()
{
char[] upperCase = { 'A', 'B', 'C'};
char[] lowerCase = { 'x', 'y', 'z'};
var joinQuery1 =
from upper in upperCase
from lower in lowerCase
select new { upper, lower};
var joinQuery2 =
from lower in lowerCase
where lower != 'x'
from upper in upperCase
select new { lower, upper };
// Execute the queries.
Console.WriteLine("Cross join:");
foreach (var pair in joinQuery1)
{
Console.WriteLine("{0} is matched to {1}", pair.upper, pair.lower);
}
Console.WriteLine("Filtered non-equijoin:");
foreach (var pair in joinQuery2)
{
Console.WriteLine("{0} is matched to {1}", pair.lower, pair.upper);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Output: Cross join:
A is matched to x
A is matched to y
A is matched to z
B is matched to x
B is matched to y
B is matched to z
C is matched to x
C is matched to y
C is matched to z
Filtered non-equijoin:
y is matched to A
y is matched to B
y is matched to C
z is matched to A
z is matched to B
z is matched to C
In the first query expression it selects the Using Group ByThe The following example will make it clear: static void Main()
{
string[] Names = { "Mony", "Hamza", "Marica", "John", "Adam", "Olivia" };
var NameGroups =
from name in Names
group name by name[0];
// Execute the query.
foreach (var name in NameGroups)
{
Console.WriteLine("Names that start with the letter '{0}':", name.Key);
foreach (var name in NameGroups)
{
Console.WriteLine(name);
}
}
}
Output: Names that start with the letter 'M':
Mony
Marica
Names that start with the letter 'H':
Hamza
Names that start with the letter 'J':
John
Names that start with the letter 'A':
Adam
Names that start with the letter 'O':
Olivia
Now let's add a little modification to the query in the previous example: var NameGroups =
from name in Names
group name by name[0];
orderby name[0]
The result will be: Names that start with the letter 'A':
Adam
Names that start with the letter 'H':
Hamza
Names that start with the letter 'J':
John
Names that start with the letter 'M':
Mony
Names that start with the letter 'O':
Olivia
Using intoIt can be used to create a temporary identifier to store the results of a //MSDN example
static void Main()
{
// Create a data source.
string[] words = { "apples", "blueberries", "oranges", "bananas", "apricots"};
// Create the query.
var wordGroups1 =
from w in words
group w by w[0] into fruitGroup
where fruitGroup.Count() >= 2
select new { FirstLetter = fruitGroup.Key,
Words = fruitGroup.Count() };
// Execute the query. Note that we only iterate over the groups,
// not the items in each group
foreach (var item in wordGroups1)
{
Console.WriteLine(" {0} has {1} elements.", item.FirstLetter, item.Words);
}
// Keep the console window open in debug mode
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Output: a has 2 elements.
b has 2 elements.
JoinInner Joinnamespace Joins
{
public class Department
{
public int ID{get; set;}
public string Name{get; set;}
}
public class Employee
{
public int ID{get; set;}
public string Name{get; set;}
public int DeptID{get; set;}
}
public void ManageJoin()
{
List < Department > Departments=new List < Department >
{new Department{ID=1, Name="Sales"},new Department
{ID=2,Name="Marketing"}};
List < Employees > Employees=new List < Employee >
{new Employee {ID=1,Name="Mony",DeptID=1},
new Employee{ID=2,Name="Tom",DeptID=2}};
//Inner Join
var innerJoinQuery = from employee in Employees
join dept in Department on employee.DeptID equals dept.ID
select new { EmployeeName = employee.Name,
DeptName = dept.Name };
}
}
The previous example will return each employee name and the department name. Group JoinA Left Outer JoinIn a Let's modify the previous example to apply var LeftouterJoinQuery = from employee in Employees
join dept in Department on employee.DeptID equals dept.ID
select new { EmployeeName = employee.Name,
DeptName = dept.Name } into empgroup
select empgroup.DefaultIfEmpty(new
{ EmployeeName = employee.Name, DeptName =
"No Department"});
Now it selects all the employees including those who are not attached to department yet. Auto-Implemented PropertiesYou can use Auto Implemented Properties when no Additional logic is required, but you have to declare both a //Auto Implemented Properties are used in the previous example, you can check it.
Partial Method DefinitionsA partial Hope that I succeeded in making the C# 3.0 features quite clear. Waiting for your feedback.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||