You are on page 1of 69

Aishwarya Lakshmi 1

C# Notes

multi-paradigm: structured, imperative, object-oriented, event-


Paradigm
driven, functional, generic

Appeared in 2001

Designed by Microsoft

Developer Microsoft

Stable release 4.0 (April 12, 2010; 11 months ago (2010-04-12))

Typing
static, dynamic, strong, safe, nominative
discipline

Major
implementatio .NET Framework, Mono, DotGNU
ns

Dialects Cω, Spec#, Polyphonic C#

Influenced by Java, C++, Eiffel, Modula-3, Object Pascal.

Influenced D, F#, Java 5, Nemerle, Vala

Platform Common Language Infrastructure

License CLR Proprietary

Usual file
.cs
extensions

Website C# Language (MSDN)


Aishwarya Lakshmi 2
C# Notes

C#

C# is intended to be a simple, modern, general-purpose, object-oriented programming language.


Aishwarya Lakshmi 3
C# Notes

The name "C sharp" was inspired by musical notation where a sharp indicates that the written note
should be made a semitone higher in pitch. This is similar to the language name of C++, where "++"
indicates that a variable should be incremented by 1.
Due to technical limitations of display (standard fonts, browsers, etc.) and the fact that the sharp symbol
♯ Music Sharp sign is not present on the standard keyboard, the number sign # Number sign was
chosen to represent the sharp symbol in the written name of the programming language. This convention
is reflected in the ECMA-334 C# Language Specification. However, when it is practical to do so (for
example, in advertising or in box art), Microsoft uses the intended musical symbol.
The "sharp" suffix has been used by a number of other .NET languages that are variants of existing
languages, including J# (a .NET language also designed by Microsoft which is derived from Java 1.1),
A# (from Ada), and the functional F#. The original implementation of Eiffel for .NET was called
Eiffel#, a name since retired since the full Eiffel language is now supported. The suffix has also been
used for libraries, such as Gtk# (a .NET wrapper for GTK+ and other GNOME libraries), Cocoa# (a
wrapper for Cocoa) and Qt# (a .NET language binding for the Qt toolkit).
History
During the development of the .NET Framework, the class libraries were originally written using a
managed code compiler system called Simple Managed C (SMC). In January 1999, Anders Hejlsberg
formed a team to build a new language at the time called Cool, which stood for "C-like Object Oriented
Language". Microsoft had considered keeping the name "Cool" as the final name of the language, but
chose not to do so for trademark reasons. By the time the .NET project was publicly announced at the
July 2000 Professional Developers Conference, the language had been renamed C#, and the class
libraries and ASP.NET runtime had been ported to C#.
C#'s principal designer and lead architect at Microsoft is Anders Hejlsberg, who was previously
involved with the design of Turbo Pascal, Embarcadero Delphi (formerly CodeGear Delphi and Borland
Delphi), and Visual J++. In interviews and technical papers he has stated that flaws in most major
programming languages (e.g. C++, Java, Delphi, and Smalltalk) drove the fundamentals of the Common
Language Runtime (CLR), which, in turn, drove the design of the C# language itself.
James Gosling, who created the Java programming language in 1994, and Bill Joy, a co-founder of Sun
Microsystems, the originator of Java, called C# an "imitation" of Java; Gosling further claimed that "[C#
is] sort of Java with reliability, productivity and security deleted." Klaus Kreft and Angelika Langer
(authors of a C++ streams book) stated in a blog post that "Java and C# are almost identical
programming languages. Boring repetition that lacks innovation," "Hardly anybody will claim that Java
or C# are revolutionary programming languages that changed the way we write programs," and "C#
borrowed a lot from Java - and vice versa. Now that C# supports boxing and unboxing, we'll have a very
similar feature in Java." Anders Hejlsberg has argued that C# is "not a Java clone" and is "much closer
to C++" in its design.
Since the release of C# 2.0 in November of 2005, the C# and Java languages have evolved on
increasingly divergent trajectories, becoming somewhat less similar. One of the first major departures
came with the addition of generics to both languages, with vastly different implementations. C# makes
use of reification to provide "first-class" generic objects that can be used like any other class, with code
generation performed at class-load time. By contrast, Java's generics are essentially a language syntax
feature, and they do not affect the generated byte code because the compiler performs type erasure on
the generic type information after it has verified its correctness.
Aishwarya Lakshmi 4
C# Notes

Furthermore, C# has added several major features to accommodate functional-style programming,


culminating in their LINQ extensions released with C# 3.0 and its supporting framework of Lambda
Expressions, Extension Methods, and anonymous classes. These features enable C# programmers to use
functional programming techniques, such as closures, when it is advantageous to their application. The
LINQ extensions and the functional imports help developers reduce the amount of "boilerplate" code
that is included in common tasks like querying a database, parsing an xml file, or searching through a
data structure, shifting the emphasis onto the actual program logic to help improve readability and
maintainability.
In the course of its development, the C# language has gone through several versions:

Versi Language specification .NET


Date Visual Studio
on ECMA ISO/IEC Microsoft Framework

January January .NET Visual Studio


C# 1.0
December 2002 2002 Framework 1.0 .NET 2002
April 2003
2002 October .NET Visual Studio
C# 1.2 April 2003
2003 Framework 1.1 .NET 2003

September September November .NET Visual Studio


C# 2.0 June 2006
2006 2005 2005 Framework 2.0 2005

November .NET Visual Studio


C# 3.0 August 2007
2007 Framework 3.5 2008
None
.NET Visual Studio
C# 4.0 April 2010 April 2010
Framework 4 2010
Aishwarya Lakshmi 5
C# Notes
Aishwarya Lakshmi 6
C# Notes

Summary of c# versions

What is the .NET Framework?

The .NET Framework is a new and revolutionary platform created by Microsoft for developing
C# 2.0 C# 3.0 C# 4.0 C# 5.0
(planned)
Method group Implicitly typed Dynamic Asynchronous
conversions local variables binding methods
(delegates) Object and
collection
initializers
Private setters Auto- Named and
Featur (properties) Implemented optional
es properties arguments
Nullable types Anonymous
added types
Iterators Extension Compiler as a
methods service
Anonymous methods Query Generic co-
expressions and
Partial types Lambda contravariance
expressions
Generics Expression trees
applications.
• It is a platform for application developers.
• It is a Framework that supports Multiple Language and Cross language integration.
• IT has IDE (Integrated Development Environment).
• Framework is a set of utilities or can say building blocks of your application system.
• .NET Framework provides GUI in a GUI manner.
• .NET is a platform independent but with help of Mono Compilation System (MCS). MCS is
a middle level interface.
• .NET Framework provides interoperability between languages i.e. Common Type System
(CTS) .
• .NET Framework also includes the .NET Common Language Runtime (CLR), which is
responsible for maintaining the execution of all applications developed using the .NET
library.
• The .NET Framework consists primarily of a gigantic library of code.
Definition: A programming infrastructure created by Microsoft for building, deploying, and running
applications and services that use .NET technologies, such as desktop applications and Web services.
Aishwarya Lakshmi 7
C# Notes

Cross Language integration

You can use a utility of a language in another language (It uses Class Language Integration).
.NET Framework includes no restriction on the type of applications that are possible. The .NET
Framework allows the creation of Windows applications, Web applications, Web services, and lot more.

The .NET Framework has been designed so that it can be used from any language, including C#, C++,
Visual Basic, JScript, and even older languages such as COBOL.

Difference between Visual Studio and Visual Studio .NET

Visual Studio Visual Studio


It is object based It is object oriented
Internet based application All developing facilities in internet based
- Web Application application
- Web services
- Internet enable application
- Third party API
- Peer to peer Application
Poor error handling Exception/Error Advance error handler and debugger
Memory Management System Level Task Memory Management Application Domain with
help of GC (Garbage Collector)
DLL HELL VS .NET has solved DLL HELL Problem

Web Application
All websites are example of web application. They use a web server.

Internet Enabled Application


They are desktop application. Yahoo messenger is an example of desktop application.

Peer to Peer
Communication through computers through some system.

Web Services
It doesn't use web-based server. Internet payment systems are example of web services.

DLL Hell
"DLL Hell" refers to the set of problems caused when multiple applications attempt to share a common
component like a dynamic link library (DLL) or a Component Object Model (COM) class.

The reason for this issue was that the version information about the different components of an
application was not recorded by the system. (Windows Registry cannot support the multiple versions of
same COM component this is called the dll hell problem.)

.Net Framework provides operating systems with a Global Assembly Cache (GAC). This Cache is a
repository for all the .Net components that are shared globally on a particular machine. When a .Net
component is installed onto the machine, the Global Assembly Cache looks at its version, its public key,
Aishwarya Lakshmi 8
C# Notes

and its language information and creates a strong name for the component. The component is then
registered in the repository and indexed by its strong name, so there is no confusion between different
versions of the same component, or DLL.

Component Object Model (COM)


COM is an outgrowth of the OO technology. It is a specification that is based on a binary standard for
reuse through interfaces. That is, components, which are pre-compiled blocks of code, written for COM
can be reused without any dependencies on the language in which they are coded. The programming
language may be Visual Basic, C++ etc. Classes pro! vide services to single applications because they
can not communicate with other applications due to the differences in language and platform, while
components provide services to numerous applications irrespective of the languages used. There came a
number of architecture for developing both client-side and server-side components. They are OMG's
CORBA, Sun's JaveBeans and Enterprise JavaBeans and Microsoft's COM. Thus the world is full of
software components, which in turn can be of greater use for hundreds of different applications. As both
CORBA and COM supports language independence, a different software vendor can create components
using different programming languages without any integration problems.COM enables inter-process
communication.
Inter-Process Communication, which in short is known as IPC, deals mainly with the techniques and
mechanisms that facilitate communication between processes. Now, why do we need special separate
mechanisms or techniques for communicating between processes? Why isn't it possible to have
information shared between two processes without using such special mechanisms?
Let us start from something primitive. Imagine you have two glasses completely filled with water. One
glass contains hot water and the other contains cold water. What can you do to make the temperature of
water in both the glasses equal? The simplest answer will be to mix the water from both the glasses in a
glass with much bigger capacity. Once water is mixed, the temperature becomes equal after some time.

Similarly, when it comes to computer programs, we need some mechanism or medium for
communication. Primarily, processes can use the available memory to communicate with each other. But
then, the memory is completely managed by the operating system. A process will be allotted some part
of the available memory for execution. Then each process will have its own unique user space. In no
way will the memory allotted for one process overlap with the memory allotted for another process.
Imagine what would happen otherwise!
So, now the question - how do different processes with unique address space communicate with each
other? The operating system's kernel, which has access to all the memory available, will act as the
communication channel. Similar to our earlier example, where the glass with hot water is one process
address space, the glass with cold water is another, and the glass with the larger capacity is the kernel
address space, so that we pour both hot water and cold water into the glass with larger capacity.
Aishwarya Lakshmi 9
C# Notes

Architecture of .NET Framework


Aishwarya Lakshmi 10
C# Notes

Garbage Collection (GC)


One of the most important features of managed code is the concept of garbage collection. This is the
.NET method of making sure that the memory used by an application is freed up completely when the
application is no longer in use.
Prior to .NET this was mostly the responsibility of programmers, and a few simple errors in code could
result in large blocks of memory mysteriously disappearing as a result of being allocated to the wrong
place in memory. That usually meant a progressive slowdown of your computer followed by a system
crash.
.NET garbage collection works by inspecting the memory of your computer every so often and
removing anything from it that is no longer needed. There is no set time frame for this; it might happen
thousands of times a second, once every few seconds, or whenever, but you can rest assured that it will
happen.

Code Manager
Code manager invokes class loader for execution.

Architecture of CLR (Common Language Runtime )

CLS (Common Language Specification)


Aishwarya Lakshmi 11
C# Notes

It is a subset of CTS. All instruction is in CLS i.e. instruction of CTS is written in CLS. CTS checks for
its type.

CLR Data Types:


1. Value Types.
➢ Structures.
➢ Enumeration.

1. Reference Type.
➢ Class.
○ Inheritance.
○ Interfaces.

.NET supports two kind of coding

1) Managed Code
2) Unmanaged Code

Managed Code
The resource, which is with in your application domain is, managed code. The resources that are within
domain are faster. The code, which is developed in .NET framework, is known as managed code. This
code is directly executed by CLR with help of managed code execution. Any language that is written
in .NET Framework is managed code. Managed code uses CLR which in turns looks after your
applications by managing memory, handling security, allowing cross - language debugging, and so on.
Aishwarya Lakshmi 12
C# Notes

Unmanaged Code
The code, which is developed outside .NET, Framework is known as unmanaged code.

Applications that do not run under the control of the CLR are said to be unmanaged, and certain
languages such as C++ can be used to write such applications, which, for example, access low - level
functions of the operating system. Background compatibility with code of VB, ASP and COM are
examples of unmanaged code.

Unmanaged code can be unmanaged source code and unmanaged compile code.

Unmanaged code is executed with help of wrapper classes.

Wrapper classes are of two types:


1. CCW (COM callable wrapper) and
2. RCW (Runtime Callable Wrapper).
Wrapper is used to cover difference with the help of CCW and RCW.

COM callable wrapper unmanaged code


Aishwarya Lakshmi 13
C# Notes

Runtime Callable Wrapper unmanaged code


Aishwarya Lakshmi 14
C# Notes

Native Code
The code to be executed must be converted into a language that the target operating system understands, known as
native code. This conversion is called compiling code, an act that is performed by a compiler.

Under the .NET Framework, however, this is a two - stage process. With help of MSIL and JIT.

MSIL (Microsoft Intermediate Language)


It is language independent code. When you compile code that uses the .NET Framework library, you
don't immediately create operating system - specific native code.

Instead, you compile your code into Microsoft Intermediate Language (MSIL) code. The MSIL code is
not specific to any operating system or to any language.

JIT (Just-in-Time)

Just - in - Time (JIT) compiler, which compiles MSIL into native code that is specific to the OS and
machine architecture being targeted. Only at this point can the OS execute the application. The just - in -
time part of the name reflects the fact that MSIL code is only compiled as, and when, it is needed.

In the past, it was often necessary to compile your code into several applications, each of which targeted
a specific operating system and CPU architecture. Often, this was a form of optimization.
Aishwarya Lakshmi 15
C# Notes

This is now unnecessary, because JIT compilers (as their name suggests) use MSIL code, which is
independent of the machine, operating system, and CPU. Several JIT compilers exist, each targeting a
different architecture, and the appropriate one will be used to create the native code required.

The beauty of all this is that it requires a lot less work on your part - in fact, you can forget about system
- dependent details and concentrate on the more interesting functionality of your code.

JIT are of three types:


1. Pre JIT
2. Econo JIT
3. Normal JIT
Pre JIT
It converts all the code in executable code and it is slow

Econo JIT
It will convert the called executable code only. But it will convert code every time when a code is called
again.

Normal JIT
It will only convert the called code and will store in cache so that it will not require converting code
again. Normal JIT is fast.

Assemblies
When you compile an application, the MSIL code created is stored in an assembly. Assemblies include
both executable application files that you can run directly from Windows without the need for any other
programs (these have a .exe file extension), and libraries (which have a .dll extension) for use by other
applications.

In addition to containing MSIL, assemblies also include meta information (that is, information about the
information contained in the assembly, also known as metadata) and optional resources (additional data
used by the MSIL, such as sound files and pictures).

The meta information enables assemblies to be fully self - descriptive. You need no other information to
use an assembly, meaning you avoid situations such as failing to add required data to the system registry
and so on, which was often a problem when developing with other platforms.

This means that deploying applications is often as simple as copying the files into a directory on a
remote computer. Because no additional information is required on the target systems, you can just run
an executable file from this directory and (assuming the .NET CLR is installed) you're good to go.

Of course, you won't necessarily want to include everything required to run an application in one place.
You might write some code that performs tasks required by multiple applications. In situations like that,
it is often useful to place the reusable code in a place accessible to all applications. In the .NET
Framework, this is the Global Assembly Cache (GAC). Placing code in the GAC is simple - you just
place the assembly containing the code in the directory containing this cache.
Aishwarya Lakshmi 16
C# Notes

ARRAYS
Arrays works as collections of items, for instance strings. You can use them to gather items in a single
group, and perform various operations on them, e.g. sorting. Besides that, several methods within the
framework work on arrays, to make it possible to accept a range of items instead of just one. This fact
alone makes it important to know a bit about arrays.

Arrays are declared much like variables, with a set of [] brackets after the datatype, like this:

string[] names;

You need to instantiate the array to use it, which is done like this:

string[] names = new string[2];

The number (2) is the size of the array, that is, the amount of items we can put in it. Putting items into
the array is pretty simple as well:

names[0] = "John Doe";

But why 0? As it is with so many things in the world of programming, the counting starts from 0 instead
of 1. So the first item is indexed as 0, the next as 1 and so on. You should remember this when filling
the array with items, because overfilling it will cause an exception. When you look at the initializer,
setting the array to a size of 2, it might seem natural to put item number 0, 1 and 2 into it, but this is
one item too much. If you do it, an exception will be thrown. We will discuss exceptions in a later
chapter.

Earlier, we learned about loops, and obviously these go great with arrays. The most common way of
getting data out of an array, is to loop through it and perform some sort of operation with each value.
Let's use the array from before, to make a real example:

using System;

using System.Collections;

namespace ConsoleApplication1

class Program

static void Main(string[] args)

{
Aishwarya Lakshmi 17
C# Notes

string[] names = new


string[2];

names[0] = "John Doe";

names[1] = "Jane Doe";

foreach(string s in names)

Console.WriteLine(s);

Console.ReadLine();

We use the foreach loop, because it's the easiest, but of course we could have used one of the other
types of loop instead. The for loop is good with arrays as well, for instance if you need to count each
item, like this:

for(int i = 0; i < names.Length; i++)

Console.WriteLine("Item number " +


i + ": " + names[i]);

It's actually very simple. We use the Length property of the array to decide how many times the loop
should iterate, and then we use the counter (i) to output where we are in the process, as well as get the
item from the array. Just like we used a number, a so called indexer, to put items into the array, we can
use it to get a specific item out again.

I told you earlier that we could use an array to sort a range of values, and it's actually very easy. The
Array class contains a bunch of smart methods for working with arrays. This example will use numbers
instead of strings, just to try something else, but it could just as easily have been strings. I wish to show
you another way of populating an array, which is much easier if you have a small, predefined set of
items that you wish to put into your array. Take a look:

int[] numbers = new int[5] { 4, 3, 8, 0, 5 };

With one line, we have created an array with a size of 5, and filled it with 5 integers. By filling the array
like this, you get an extra advantage, since the compiler will check and make sure that you don't put too
many items into the array. Try adding a number more - you will see the compiler complain about it.

Actually, it can be done even shorter, like this:


Aishwarya Lakshmi 18
C# Notes

int[] numbers = { 4, 3, 8, 0, 5 };

This is short, and you don't have to specify a size. The first approach may be easier to read later on
though.

Let's try sorting the array - here's a complete example:

using System;

using System.Collections;

namespace ConsoleApplication1

class Program

static void Main(string[] args)

int[] numbers = { 4, 3, 8,
0, 5 };

Array.Sort(numbers);

foreach(int i in numbers)

Console.WriteLine(i);

Console.ReadLine();

The only real new thing here is the Array.Sort command. It can take various parameters, for various
kinds of sorting, but in this case, it simply takes our array. As you can see from the result, our array has
Aishwarya Lakshmi 19
C# Notes

been sorted. The Array class has other methods as well, for instance the Reverse() method. You can
look it up in the documentation to see all the features of the Array class.

The arrays we have used so far have only had one dimension. However, C# arrays can be
multidimensional, sometimes referred to as arrays in arrays. Multidimensional arrays come in two
flavors with C#: Rectangular arrays and jagged arrays. The difference is that with rectangular arrays, all
the dimensions have to be the same size, hence the name rectangular. A jagged array can have
dimensions of various sizes. Multidimensional arrays are a heavy subject, and a bit out of the scope of
this tutorial.

Covariance and Contravariance in Delegates (C#


Programming Guide)
Visual Studio 2005

Other Versions

• Visual Studio 2010


• Visual Studio 2008

Covariance and contravariance provide a degree of flexibility when matching method signatures with
delegate types. Covariance permits a method to have a more derived return type than what is defined in
the delegate. Contravariance permits a method with parameter types that are less derived than in the
delegate type.

Example 1 (Covariance)

This example demonstrates how delegates can be used with methods that have return types that are
derived from the return type in the delegate signature. The data type returned by SecondHandler is of
type Dogs, which derives from the Mammals type that is defined in the delegate.

VB
Aishwarya Lakshmi 20
C# Notes

C#

C++

F#

JScript

Copy

class Mammals

class Dogs : Mammals

class Program

// Define the delegate.

public delegate Mammals HandlerMethod();

public static Mammals FirstHandler()

return null;

public static Dogs SecondHandler()


Aishwarya Lakshmi 21
C# Notes

return null;

static void Main()

HandlerMethod handler1 = FirstHandler;

// Covariance allows this delegate.

HandlerMethod handler2 = SecondHandler;

Example 2 (Contravariance)

This example demonstrates how delegates can be used with methods that have parameters of a type
that are base types of the delegate signature parameter type. With contravariance, you can now use one
event handler in places where, previously, you would have had to use separate handlers. For example,
you can now create an event handler that accepts an EventArgs input parameter and use it with the
Button.MouseClick event that sends a MouseEventArgs type as a parameter, and also with
TextBox.KeyDown event that sends a KeyEventArgs parameter.

VB

C#

C++

F#

JScript
Aishwarya Lakshmi 22
C# Notes

Copy

System.DateTime lastActivity;

public Form1()

InitializeComponent();

lastActivity = new System.DateTime();

this.textBox1.KeyDown += this.MultiHandler; //works with KeyEventArgs

this.button1.MouseClick += this.MultiHandler; //works with MouseEventArgs

// Event hander for any event with an EventArgs or

// derived class in the second parameter

private void MultiHandler(object sender, System.EventArgs e)

lastActivity = System.DateTime.Now;

Covariance and Contravariance in C#3


Posted on March 9, 2009 by Julien Palard

A short introduction to Covariance and Contravariance in C# 3 preparing you to an article


about that in C# 4.
So what is covariance ?
Aishwarya Lakshmi 23
C# Notes

Covariance is basically using a method which returns something derived from the expected
type.

An exemple ? It’s safe to have a method returning a cat when you expect it to return an animal.

In C sharp it’s

public class Animal

public class Cat : Animal

public class Dog : Animal

// It's safe to say that something returns a Animal when in fact this
thing returns a Cat

class Covariance

{
Aishwarya Lakshmi 24
C# Notes

void test()

Func<Animal> a = Method; // OK

Func<Animal> b = delegate { return new Cat(); }; // OK

Func<Animal> c = () => new Cat(); // OK

Cat Method()

return new Cat();

So Funcs a, b, and c are returning animals which in fact are cats, which is true.

And, what is contravariance ?


Contravariance is basically using a method which takes something which is a parent of the
expected type.
An exemple ? It’s safe to have a method taking an animal when you expect it to take a cat

// It's safe to say that something can take a Cat if in fact this thing
can take any Animal

class Contravariance

{
Aishwarya Lakshmi 25
C# Notes

static void test()

Action<Cat> a = Method; // OK

Action<Cat> b = delegate(Animal value) { }; // ERROR

// From C#3 Specification :

// $7.14.1 Anonymous function signatures :

// [...] contra-variance of anonymous function parameter


types is not supported.

Action<Cat> d = (Animal value) => { }; // idem...


anonymous... not supported.

public static void Method(Animal value)

So Action a take Cats, but in fact can take any Animals, so it’s safe

Ienumerators
Description

This article explains how to implement enumerators in C#.

We know how to use foreach for built-in types of C#.But how do we Use for objects of our class.
For
Aishwarya Lakshmi 26
C# Notes

class Employee
{
}

how do we use foreach for the objects of Employee.

Step#1:
To foreach construct for user-defined classes the first thing we have to do is Imlplement the
interface IEnumerable. Then Ienumerable interface has a method called GetEnumerator() which
returns an object of IEnumerator.
Step#2:
Next we have to implement IEnumerator interface.The IEnumerator has 3 methods namely
Reset(),Current(),MoveNext().After we code for the 3 methods we are able to use foreach() for our
UDC(User Defined Classes).
Step#3:
How does foreach works when we use foreach() construct it first Calls MoveNext() if it returns true
then the loop is continued to the value from the Current() method call.Reset() is used to set the
Enumerator to begining position.
Let's run through a coding sample which will make things clear:

The source code has 2 classes namely Employee,Employees. Employee class hold information
about each Employee. The Employees class hold array of Employee objects.
Source Code Explanation:
1. Create Employees class object

Employees EmpList=new Employees();

2. Create Employee class objects

Employee e1=new Employee(1,"Employee#1",1250.75);


Employee e2=new Employee(2,"Employee#2",1275.85);

3. Add Employee object to Employees class object

EmpList.AddEmployee(e1);
EmpList.AddEmployee(e2);

4. foreach(Employee emp in EmpList)


{
Console.WriteLine(emp);
}

When this statement is executed it will call the GetEnumerator() method of the Employees
class to get the IEnumerator object.Then it calls the MoveNext() method since it returns
true it calls the Current() method and return the Employee object.which is printed.this same
sequence is repeated for 2nd Employee.During the third time call MoveNext() returns false
and it exits the foreach construct.
Aishwarya Lakshmi 27
C# Notes

5. To clearly get the underhood of Enumerator() see the code below which does the above
sequence:

IEnumerator EmpEnumerator=EmpList.GetEnumerator(); //Getting the Enumerator


EmpEnumerator.Reset(); //Position at the Beginning
While(EmpEnumerator.MoveNext()) //Till not finished do print
{
Console.WriteLine((Employee)EmpEnumerator.Current);
}
}
Complete Source Code:

// Source Code starts here


using System;
using System.Collections;
class Employee
{
private int Id;
private string Name;
private double Salary;
public Employee(int id,string name,double salary)
{
this.Id=id;
this.Name=name;
this.Salary=salary;
}
public int ID
{
get
{
return this.Id;
}
}
public override string ToString()
{
return "Id:" + this.Id.ToString() + "\nName:" + Name + "\nSalary:" + Salary.ToString();
}
}
class Employees:IEnumerable,IEnumerator
{
ArrayList EmpList=new ArrayList();
private int Position=-1;
public void AddEmployee(Employee oEmp)
{
EmpList.Add(oEmp);
}
/* Needed since Implementing IEnumerable*/
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
/* Needed since Implementing IEnumerator*/
Aishwarya Lakshmi 28
C# Notes

public bool MoveNext()


{
if(Position<EmpList.Count-1)
{
++Position;
return true;
}
return false;
}
public void Reset()
{
Position=-1;
}
public object Current
{
get
{
return EmpList[Position];
}
}
public static void Main()
{
Employees EmpList=new Employees();
Employee e1=new Employee(1,"Employee#1",1250.75);
Employee e2=new Employee(2,"Employee#2",1275.85);
EmpList.AddEmployee(e1);
EmpList.AddEmployee(e2);
Console.WriteLine("Enumerating Employees using foreach");
foreach(Employee emp in EmpList)
{
Console.WriteLine(emp);
}
Console.WriteLine("\nEnumerating Employee Creating object of IEnumerator");
IEnumerator EmpEnumerator=EmpList.GetEnumerator();
EmpEnumerator.Reset();
while(EmpEnumerator.MoveNext())
{
Console.WriteLine((Employee)EmpEnumerator.Current);
}
}
}

Ienumerator and Ienumerable


In the .NET Framework, there are two interfaces designed to allow you to iterate easily over collections
of objects as you would typically do in a for loop. Many classes in the .NET Framework have
implemented these interfaces and do their work behind the scenes so you don’t have to worry about how
it is done. However, sometimes you want to have the control to do this yourself.
Maybe you have the need to create a custom class that holds a collection of objects, and you want to be
able to iterate over them. It’s pretty straightforward to do this in C# or VB.NET. You have to implement
two interfaces called IEnumerable and IEnumerator. Below is a trivial example (because it’s already
Aishwarya Lakshmi 29
C# Notes

possible to do this with the List class) that illustrates how you would go about implementing these to
iterate over a collection of string objects:

using System;

using System.Collections.Generic;

using System.Collections;

namespace Demo

public class TestOverride : IEnumerable<string>

private List<string> _values;

public TestOverride(List<string> values)

_values = values;

public IEnumerator<string> GetEnumerator()

return new TestOverrideEnumerator(_values);

IEnumerator IEnumerable.GetEnumerator()

return GetEnumerator();

}
Aishwarya Lakshmi 30
C# Notes

protected class TestOverrideEnumerator : IEnumerator<string>

private List<string> _values;

private int _currentIndex;

public TestOverrideEnumerator(List<string> values)

_values = new List<string>(values);

Reset();

public string Current

get { return _values[_currentIndex]; }

public void Dispose() {}

object IEnumerator.Current

get { return Current; }

public bool MoveNext()


Aishwarya Lakshmi 31
C# Notes

_currentIndex++;

return _currentIndex < _values.Count;

public void Reset()

_currentIndex = -1;

I’m sure there’s a better way to do this, but it should help you get started. Note that you have to
implement both classes and that the most work is done in the class that implements IEnumerator. Also
note that you can use generics (in this case force it to iterate only over string objects).
You would invoke this functionality this way:

List<string> collection = new List<string>();

collection.Add("abc");

collection.Add("def");

collection.Add("ghi");

TestOverride collectionWrapper = new TestOverride(collection);

foreach (string x in collectionWrapper)

Console.Out.WriteLine(x);

Anonymous types
Aishwarya Lakshmi 32
C# Notes

With the introduction of .NET 3.5 C# includes the “var” keyword to support anonymous types. One
important motivation for this was to make code written with LINQ (Language-Integrated Query) easier
to read. So what is an anonymous type? Anonymous types simply mean that you don’t specify the type —
but let the compiler do it instead.
To understand how LINQ works, and to realize that its more than just syntactic sugar added to C# we
first need to review a couple of basic concepts that when combined lead to LINQ.
Simple definitions, simplified
In typical C# you will always carefully spell out your definitions:
string MyString = “Hello World”;
From the right side of the declaration it is obvious that only one type (string) will ever match this
definition. So instead of us doing the work, why not let the compiler figure this out?
var MyString = “Hello World”;
The above definition will also create a string variable named “MyString”. It is important to note that C#
is still strongly typed — unlike scripted languages such as Visual Basic (or PHP) once you have
assigned the variable type it sticks. The following will not work:
var MyString2 = “Hello World”;
MyString2 = 123; // Nice try, but no banana
The compiler will throw an implicit conversion error as 123 cannot be assigned to a string.
The above was an impressive (if somewhat pointless) example of what an anonymous type is. For
simple types such as strings, integers etc anonymous types offer little benefits. It is even possible to
argue that it reduces your code readability.
Using anonymous types for creating arrays
We are not limited to simple types – the following example show how we can create an anonymous
array of integers:
int[] myIntArray = new int[] { 1 , 2 , 3 , 4 , 5 , 6 };
var myIntArrayVar = new [] { 1 , 2 , 3 , 4 , 5 , 6 };
The above two examples are equivalent. You still need to specify that you want to create an array using
new. You are however limited by how flexible the compiler is. A mixed array is a little too much and we
need to force it down to an object array:
var myMixedArray = new [] { 1, “two” , 3 , “four” , 5 }; // this does NOT work
object[] myMixedArray = new object[] { 1, “two” , 3 , “four” , 5 }; // this is OK
Saving time and code with anonymous types
One very powerful feature of anonymous types it that they can save you a lot of work. Instead of having
to type out everything explicitly, you can have the compiler infer the definition of a complete class:
view sourceprint?

01.using System;

02.class MainClass

03.{
Aishwarya Lakshmi 33
C# Notes

04. public static void Main(string[] args)

05. {

06. var Person = new { Name = "Michael", Age = 23 };

07. Console.WriteLine("Name: {0} Age: {1}",Person.Name,Person.Age);

08. }

09.}

The compiler creates an anonymous definition of a class and assigns to it Name and Age as public
fields. We can combine anonymous classes and anonymous arrays to create an Employee data structure.
Note that we use a “Var” in the ForEach loop. Because we are combining anonymous types it is
impossible to determine the correct type to loop over each element in the array. Thankfully we can ask
the compiler to fill in the correct iterator type for us:
view sourceprint?

01.using System;

02.class MainClass

03.{

04. public static void Main(string[] args)

05. {

06. var Person1 = new { Name = "Michael", Age = 23 };

07. var Person2 = new { Name = "Sandra", Age = 33 };

08. var Employees = new [] { Person1, Person2 };

09. foreach (var P in Employees)

10. Console.WriteLine("Name: {0} Age: {1}",P.Name,P.Age);

11. }

12.}

As Employees is an array we can use an iterator to step through it as shown above, but we can just as
easily use a for loop:
view sourceprint?

01.using System;

02.class MainClass

03.{
Aishwarya Lakshmi 34
C# Notes

04. public static void Main(string[] args)

05. {

06. var Person1 = new { Name = "Michael", Age = 23 };

07. var Person2 = new { Name = "Sandra", Age = 33 };

08. var Employees = new [] { Person1, Person2 };

09. for(int Lp = 0; Lp < Employees.Length; Lp++)

10. Console.WriteLine("Name: {0} Age:


{1}",Employees[Lp].Name,Employees[Lp].Age);

11. }

12.}

Lambda expressions and anonymous methods


Lambda expressions are an extension of Anonymous Methods which were introduced in C# 2.0 Lambda
expressions add a lot of power to C#, but they can be hard to understand. They are however great for
small filters than can be passed on to functions as variables as we will see in the following example:
Func<int,bool> mySeniorStaffFilter = a => a > 35;
Console.WriteLine(“36 is senior? {0}”,mySeniorStaffFilter(36));
The above function can be defined anywhere inside your code. It takes a single integer as a parameter
and returns a boolean. The integer is defined as “a”, and the function checks whether a is larger than 35.
Using the “old” anonymous methods we could have written the above as:
Func<int,bool> mySeniorStaffFilter = delegate(int a) { return a > 35; };
The Lambda expression syntax is the same, but shorter and this make them slightly easier to understand.
Combining Lambda expressions with Queries
If you have used Intellisense in Visual Studio or the greatly improved object browser in MonoDevelop
2.0 you will discover that with C# 3.0 arrays have a much larger set of methods associated with them.
One of these methods is “Where”. It takes a filter as an argument ; and then simply applies each member
of the array to the filter. If the filter returns “true” the value is yielded and returned in a sub-set.
In plain language: If you have an array of employees you can pass mySeniorStaffFilter function to the
Where method. It checks every staff member to see if their age is over 35 and then returns an array
containing only those members of staff.
var SeniorStaff = Employees.Where(s => s.Age > 35);
The following code example shows how this works:
view sourceprint?

01.using System;

02.using System.Linq;

03. class MainClass


Aishwarya Lakshmi 35
C# Notes

04. {

05. public static void Main(string[] args)

06. {

07. var Employees = new [] { new { Name = "Michael", Age = 23 },

08. new { Name = "Anton", Age = 43 },

09. new { Name = "Nadia", Age = 36 },

10. new { Name = "Lydia", Age = 34 } };

11. var SeniorStaff = Employees.Where(s => s.Age > 35);

12. foreach(var Member in SeniorStaff)

13. Console.WriteLine("Name: {0} Age: {1}",Member.Name,Member.Age);

14. }

15. }

From the above you can see that the compiler needs to infers,create and apply several anonymous types
to create a working code sample. We thankfully can use “var” to specify our SeniorStaff sub-set. Behind
the scenes the compiler has created an anonymous IEnumberable for SeniorStaff that contains our
Employee records with anonymous staff members. And for the Where method it applied an anonymous
delegate to create the correct filter.
And this leads us to the first real “LINQ” statement.
var SeniorStaff = from S in Employees where S.Age > 35 select S;
When you take away the syntactic sugar the C# compiler will build from this the same (or very similar)
“Employees.Where(s => s.Age > 35)” statement. Using the same anonymous methods, variables and
functions as we used earlier.
This took a lot of getting to. It is however important to understand that LINQ is implemented in C#
through basic, strongly typed variables and methods.
To keep the complexity of our C# code down the “var” keyword was added allowing the programmer to
focus on coding the logic of the program instead of having to write long hand type definitions for each
variable.
Q. Is var typesafe?
There’s no concern about type-safety, as the variable created is not dynamic. It’s just compiler magic
and any type unsafe calls you make will get caught.
Q. Is there a performance penalty for using “var” ?
The var keyword only tells the compiler to infer the type from the assignment, there’s no runtime
difference, so no, there’s no penalty performance wise.
Q. On using anonymous definitions in large projects
Aishwarya Lakshmi 36
C# Notes

Anonymous types cannot be shared across assembly boundaries. The compiler ensures that there is at
most one anonymous type for a given sequence of property name/type pairs within each assembly. To
pass structures between assemblies you will need to properly define them.

Anonymous Types in C#
SpreadsheetGear: ASP.NET Excel Reporting
Easily create richly formatted Excel reports without Excel using the new generation of
spreadsheet technology built from the ground up for scalability and reliability. learn more

This was introduced in C# 3.0.


Anonymous types are on the fly classes or unnamed classes.
For example i define a class with the following :
view source

print?

01 class Employee

02 {

03 private int _EmpID;

04 private string _EmpName;

05 public int EmpID

06 {

07 get

08 {

09 return _EmpID;

10 }

11 set
Aishwarya Lakshmi 37
C# Notes

12 {

13 _EmpID = value;

14 }

15 }

16 public string EmpName

17 {

18 get

19 {

20 return _EmpName;

21 }

22 set

23 {

24 _EmpName = value;

25 }

26 }

27

28 }

Here’s how i create an object


view source
Aishwarya Lakshmi 38
C# Notes

print?

1 Employee objEmployee = new Employee { EmpID = 1, EmpName = "senthil" };

Note that the properties/ members are initialized here through object initializer .
An object initializer can specify values for one or more properties of an object.
class members such as methods or events are not allowed.
I can also create an object via Implicit type reference .
view source

print?

1 var objEmployee = new Employee { EmpID = 1, EmpName = "senthil" };

Here’s how i use the Anonymous type


view source

print?

var objEmployee1 = new { EmpID = 1, EmpName = "senthil"


1
};

The actual type of this would be anonymous .


It has no name .
This feature will be extremly be helpful when LINQ is used .
The Visual Studio will provide us the full intellisense support for the anonymous type along with the
compile time checking.
Aishwarya Lakshmi 39
C# Notes

Little observations on the anonymous type .


1. I created another anonymous object with the same parameter and when 1 compare the type of
objEmployee1 , objEmployee2 , they are same in the eyes of the compiler .
view source

print?

var objEmployee2 = new { EmpID = 6, EmpName = "trivium"


1
};

2. I tried changing the order of the parameters of objuEmployee2.


view source

print?

1 var objEmployee2 = new { EmpName = "trivium",EmpID = 6 };

The type name here i got were different .

C# Var Examples
Top of Form

dotnetperls.com Go

Bottom of Form

You are unfamiliar with the var keyword in the C# programming language
and want to look at an example of it with explanations. It doesn't seem to fit
with the rest of the language. This short information sheet has an example
of var along with some discussion, with code in the C# language.
Example
First, we look at some examples of using this new keyword in the C#
language. Here is a code example of the var keyword being used in three
different contexts. You need the .NET Framework 3.5 or a later version to
run this.
Aishwarya Lakshmi 40
C# Notes

Program that uses var keyword [C#]

using System;

using System.Collections.Generic;

using System.Linq;

class Program

public static void Main()

// 1.

// var is always available, not just in Linq.

var cat = new List<int>

1,

2,

7,

};

// Hover over the 'var' keyword and Visual Studio 2008

// will tell you what it really is.

// 2.

// This example display odd numbers.

// Returns IEnumerable<T> (where T is int).


Aishwarya Lakshmi 41
C# Notes

var items = from item in cat

where (item % 2 == 1)

select item;

// 3.

// Each item is an int.

foreach (var item in items)

Console.WriteLine(item);

// The previous loop is the same as this:

foreach (int item in items)

Console.WriteLine(item);

Output

1
Aishwarya Lakshmi 42
C# Notes

Description of the program. It uses var and List. The variable cat is
known to be a List. Hover over the "var" keyword and the compiler will tell
you that it's a List. Here we see the var items query. It returns
"IEnumerable<int>". You can use the foreach loop with var. You can use the
var item exactly like you can use any type.
Type systems
The C# language is strongly-typed, which means that memory is labeled by
what kind of object it contains. The language uses strong types to enforce
code quality. Variables are both memory and also type annotations. It raises
errors and warnings because it wants your code to work properly. It makes
inferences about your code and can deduce the type of a variable without
you telling it exactly.
Brevity of the language. The C# programming language is wordy. We
don't like entering text at all. Languages like C# and Java sometimes have
very long keywords. You can reduce this with var, which allows a three-
letter type to be used.
Var limitations. Here we look at an interesting limitation of the var
keyword. You can't assign a new var to null. This will result in the CS0825
warning. You can't use var as a parameter type or a return value of a
method.
Intermediate language (IL)
Here we look at the internal implementation and behavior of the var
keyword in the C# language. IL is what C# code is turned into. You can see
it with a utility called IL Disassembler provided with Visual Studio. There are
two int32 values in the IL below.

Method using var [C#]

public int ReturnValue()

var a = 5;
Aishwarya Lakshmi 43
C# Notes

int b = 5;

return a + b;

IL of the method

.method public hidebysig instance int32 ReturnValue() cil managed

// Code size 9 (0x9)

.maxstack 1

.locals init ([0] int32 result,

[1] int32 CS$1$0000)

IL_0000: nop

IL_0001: ldc.i4.5

IL_0002: stloc.0

IL_0003: ldloc.0

IL_0004: stloc.1

IL_0005: br.s IL_0007

IL_0007: ldloc.1

IL_0008: ret

} // end of method VarKW::ReturnValue

Description of the intermediate language. The int declaration is exactly


the same as the var declaration in the IL. So the .NET runtime doesn't know
that you used one or the other. Because they are compiled to the same IL,
the var keyword is therefore equally fast as strong types.
Aishwarya Lakshmi 44
C# Notes

Summary
We saw how you can use the var keyword in the C# programming language.
Find out what it stands for by hovering over it in Visual Studio. It has
similarities to #define or typedef in C++. Use var for brevity and where it
makes the code easier to understand. The var keyword has equal
performance and does not affect runtime behavior in any way.
Ten LINQ Myths
Translations: English | Spanish
Here are ten root causes of the most common misunderstandings—distilled from
many hundreds of questions on the LINQ forums.

Myth #1
All LINQ queries must start with the ‘var’ keyword. In fact, the very
purpose of the ‘var’ keyword is to start a LINQ query!

The var keyword and LINQ queries are separate concepts. The purpose of var is to
let the compiler guess what type you want for a local variable declaration (implicit
typing). For example, the following:

var s = "Hello";

is precisely equivalent to:

string s = "Hello";

because the compiler infers that s is a string.


Similarly, the following query:

string[] people = new [] { "Tom", "Dick", "Harry" };

var filteredPeople = people.Where (p => p.Length > 3);

is precisely equivalent to:

string[] people = new [] { "Tom", "Dick", "Harry" };

IEnumerable<string> filteredPeople = people.Where (p => p.Length > 3);


Aishwarya Lakshmi 45
C# Notes

You can see here that all that we're achieving with var is to abbreviate
IEnumerable<string>. Some people like this because it cuts clutter; others
argue that implicit typing can make it less clear what's going on.
Now, there are times when a LINQ query necessitates the use of var. This is when
projecting an anonymous type:

string[] people = new [] { "Tom", "Dick", "Harry" };

var filteredPeople = people.Select (p => new { Name = p, p.Length });

Here is an example of using an anonymous type outside the context of LINQ query:

var person = new { Name="Foo", Length=3 };

Myth #2
All LINQ queries must use query syntax.

There are two kinds of syntax for queries: lambda syntax and query syntax (or
query comprehension syntax). Here's an example of lambda syntax:

string[] people = new [] { "Tom", "Dick", "Harry" };

var filteredPeople = people.Where (p => p.Length > 3);

Here's the same thing expressed in query syntax:

string[] people = new [] { "Tom", "Dick", "Harry" };

var filteredPeople = from p in people where p.Length > 3 select p;

Logically, the compiler translates query syntax into lambda syntax. This means
that everything that can be expressed in query syntax can also be expressed in
lambda syntax. Query syntax can be a lot simpler, though, with queries that
involve more than one range variable. (In this example, we used just a single range
variable, p, so the two syntaxes were similarly simple).
Not all operators are supported in query syntax, so the two syntax styles are
complementary. For the best of both worlds, you can mix query styles in a single
statement (see Myth #5 for an example).

Myth #3
Aishwarya Lakshmi 46
C# Notes

To retrieve all customers from the customer table, you must perform a
query similar to the following:
var query = from c in db.Customers select c;

The expression:

from c in db.Customers select c

is a frivolous query! You can simply go:

db.Customers

Similarly, the following LINQ to XML query:

var xe = from e in myXDocument.Descendants ("phone") select e;

can be simplified to:

var xe = myXDocument.Descendants ("phone");

And this:

Customer customer = (from c in db.Customers where c.ID == 123 select c)

.Single();

can be simplified to:

Customer customer = db.Customers.Single (c => c.ID == 123);

Myth #4
To reproduce a SQL query in LINQ, you must make the LINQ query look
as similar as possible to the SQL query.

LINQ and SQL are different languages that employ very different concepts.
Possibly the biggest barrier in becoming productive with LINQ is the "thinking in
SQL" syndrome: mentally formulating your queries in SQL and then transliterating
them into LINQ. The result is that you're constantly fighting the API!
Once you start thinking directly in LINQ, your queries will often bear little
resemblance to their SQL counterparts. In many cases, they'll be radically simpler,
too.
Aishwarya Lakshmi 47
C# Notes

Myth #5
To do joins efficiently in LINQ, you must use the join keyword.

This is true, but only when querying local collections. When querying a database,
the join keyword is completely unnecessary: all ad-hoc joins can be accomplished
using multiple from clauses and subqueries. Multiple from clauses and subqueries
are more versatile too: you can also perform non-equi-joins.
Better still, in LINQ to SQL and Entity Framework, you can query association
properties, alleviating the need to join altogether! For instance, here's how to
retrieve the names and IDs of all customers who have made no purchases:

from c in db.Customers

where !c.Purchases.Any()

select new { c.ID, c.Name }

Or, to retrieve customers who have made no purchases over $1000:

from c in db.Customers

where !c.Purchases.Any (p => p.Price > 1000)

select new { c.ID, c.Name }

Notice that we're mixing fluent and query syntax. See LINQPad for more examples
on association properties, manual joins, and mixed-syntax queries.

Myth #6
Because SQL emits flat result sets, LINQ queries must be structured to
emit flat result sets, too.

This is a consequence of Myth #4. One of LINQ's big benefits is that you can:
1. Query a structured object graph through association properties (rather than having
to manually join)
2. Project directly into object hierarchies

The two are independent, although 1 helps 2. For example, if you want to retrieve
the names of customers in the state of WA along with all their purchases, you can
simply do the following:
Aishwarya Lakshmi 48
C# Notes

from c in db.Customers

where c.State == "WA"

select new

c.Name,

c.Purchases // An EntitySet (collection)

The hierarchical result from this query is much easier to work with than a flat result
set!
We can achieve the same result without association properties as follows:

from c in db.Customers

where c.State == "WA"

select new

c.Name,

Purchases = db.Purchases.Where (p => p.CustomerID == c.ID)

Myth #7
To do outer joins in LINQ to SQL, you must always use
DefaultIfEmpty().

This is true only if you want a flat result set. The examples in the preceding myth,
for instance, translate to a left outer join in SQL, and require no DefaultIfEmpty
operator.

Myth #8
Aishwarya Lakshmi 49
C# Notes

A LINQ to SQL or EF query will be executed in one round-trip only if


the query was built in a single step.

LINQ follows a lazy evaluation model, which means queries execute not when
constructed, but when enumerated. This means you can build up a query in as
many steps as you like, and it won't actually hit the server until you eventually
start consuming the results.
For instance, the following query retrieves the names of all customers whose name
starts with the letter 'A', and who have made at least two purchases. We build this
query in three steps:

var query = db.Customers.Where (c => c.Name.StartsWith ("A"));

query = query.Where (c => c.Purchases.Count() >= 2);

var result = query.Select (c => c.Name);

foreach (string name in result) // Only now is the query executed!

Console.WriteLine (name);

Myth #9
A method cannot return a query, if the query ends in the 'new'
operator

The trick is to project into an ordinary named type with an object initializer:

public IQueryable<NameDetails> GetCustomerNamesInState (string state)

return

from c in Customer

where c.State == state

select new NameDetails

FirstName = c.FirstName,
Aishwarya Lakshmi 50
C# Notes

LastName = c.LastName

};

NameDetails is a class that you'd define as follows:

public class NameDetails

public string FirstName, LastName;

Myth #10
The best way to use LINQ to SQL is to instantiate a single DataContext
to a static property, and use that shared instance for the life of the
application.

This strategy will result in stale data, because objects tracked by a DataContext
instance are not refreshed simply by requerying.
Using a single static DataContext instance in the middle tier of a distributed
application will cause further trouble, because DataContext instances are not
thread-safe.
The correct approach is to instantiate fresh DataContext objects as required,
keeping DataContext instances fairly short-lived. The same applies with Entity
Framework.

Basic LINQ Query Operations (C#)


Visual Studio 2010

Other Versions
Aishwarya Lakshmi 51
C# Notes

• Visual Studio 2008

This topic gives a brief introduction to LINQ query expressions and some of the typical kinds of
operations that you perform in a query. More detailed information is in the following topics:
LINQ Query Expressions (C# Programming Guide)
Standard Query Operators Overview

Note

If you already are familiar with a query language such as SQL or XQuery, you can skip most of this
topic. Read about the "from clause" in the next section to learn about the order of clauses in LINQ
query expressions.

Obtaining a Data Source

In a LINQ query, the first step is to specify the data source. In C# as in most programming languages a
variable must be declared before it can be used. In a LINQ query, the from clause comes first in order to
introduce the data source (customers) and the range variable (cust).

VB

C#

C++

F#

JScript

Copy

//queryAllCustomers is an IEnumerable<Customer>
Aishwarya Lakshmi 52
C# Notes

var queryAllCustomers = from cust in customers

select cust;

The range variable is like the iteration variable in a foreach loop except that no actual iteration occurs in
a query expression. When the query is executed, the range variable will serve as a reference to each
successive element in customers. Because the compiler can infer the type of cust, you do not have to
specify it explicitly. Additional range variables can be introduced by a let clause. For more information,
see let clause (C# Reference).

Note

For non-generic data sources such as ArrayList, the range variable must be explicitly typed. For more
information, see How to: Query an ArrayList with LINQ and from clause (C# Reference).

Filtering

Probably the most common query operation is to apply a filter in the form of a Boolean expression. The
filter causes the query to return only those elements for which the expression is true. The result is
produced by using the where clause. The filter in effect specifies which elements to exclude from the
source sequence. In the following example, only those customers who have an address in London are
returned.

VB

C#

C++

F#

JScript
Aishwarya Lakshmi 53
C# Notes

Copy

var queryLondonCustomers = from cust in customers

where cust.City == "London"

select cust;

You can use the familiar C# logical AND and OR operators to apply as many filter expressions as
necessary in the where clause. For example, to return only customers from "London" AND whose name is
"Devon" you would write the following code:

VB

C#

C++

F#

JScript

Copy

where cust.City=="London" && cust.Name == "Devon"

To return customers from London or Paris, you would write the following code:
Aishwarya Lakshmi 54
C# Notes

VB

C#

C++

F#

JScript

Copy

where cust.City == "London" || cust.City == "Paris"

For more information, see where clause (C# Reference).

Ordering

Often it is convenient to sort the returned data. The orderby clause will cause the elements in the
returned sequence to be sorted according to the default comparer for the type being sorted. For
example, the following query can be extended to sort the results based on the Name property. Because
Name is a string, the default comparer performs an alphabetical sort from A to Z.

VB
Aishwarya Lakshmi 55
C# Notes

C#

C++

F#

JScript

Copy

var queryLondonCustomers3 =

from cust in customers

where cust.City == "London"

orderby cust.Name ascending

select cust;

To order the results in reverse order, from Z to A, use the orderby…descending clause.
For more information, see orderby clause (C# Reference).

Grouping

The group clause enables you to group your results based on a key that you specify. For example you
could specify that the results should be grouped by the City so that all customers from London or Paris
are in individual groups. In this case, cust.City is the key.

Note

The types are explicit in the following examples to illustrate the concept. You could also use implicit
typing for custQuery, group, and customer to let the compiler determine the exact type.
Aishwarya Lakshmi 56
C# Notes

VB

C#

C++

F#

JScript

Copy

// queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>>

var queryCustomersByCity =

from cust in customers

group cust by cust.City;

// customerGroup is an IGrouping<string, Customer>

foreach (var customerGroup in queryCustomersByCity)

Console.WriteLine(customerGroup.Key);

foreach (Customer customer in customerGroup)

Console.WriteLine(" {0}", customer.Name);

}
Aishwarya Lakshmi 57
C# Notes

When you end a query with a group clause, your results take the form of a list of lists. Each element in
the list is an object that has a Key member and a list of elements that are grouped under that key. When
you iterate over a query that produces a sequence of groups, you must use a nested foreach loop. The
outer loop iterates over each group, and the inner loop iterates over each group's members.
If you must refer to the results of a group operation, you can use the into keyword to create an identifier
that can be queried further. The following query returns only those groups that contain more than two
customers:

VB

C#

C++

F#

JScript

Copy

// custQuery is an IEnumerable<IGrouping<string, Customer>>

var custQuery =

from cust in customers

group cust by cust.City into custGroup

where custGroup.Count() > 2

orderby custGroup.Key
Aishwarya Lakshmi 58
C# Notes

select custGroup;

For more information, see group clause (C# Reference).

Joining

Join operations create associations between sequences that are not explicitly modeled in the data
sources. For example you can perform a join to find all the customers and distributors who have the
same location. In LINQ the join clause always works against object collections instead of database tables
directly.

VB

C#

C++

F#

JScript

Copy

var innerJoinQuery =

from cust in customers

join dist in distributors on cust.City equals dist.City

select new { CustomerName = cust.Name, DistributorName = dist.Name };


Aishwarya Lakshmi 59
C# Notes

In LINQ you do not have to use join as often as you do in SQL because foreign keys in LINQ are
represented in the object model as properties that hold a collection of items. For example, a Customer
object contains a collection of Order objects. Rather than performing a join, you access the orders by
using dot notation:
Copy

from order in Customer.Orders...

For more information, see join clause (C# Reference).

Selecting (Projections)

The select clause produces the results of the query and specifies the "shape" or type of each returned
element. For example, you can specify whether your results will consist of complete Customer objects,
just one member, a subset of members, or some completely different result type based on a
computation or new object creation. When the select clause produces something other than a copy of
the source element, the operation is called a projection. The use of projections to transform data is a
powerful capability of LINQ query expressions. For more information, see Data Transformations with LINQ
(C#) and select clause (C# Reference).

LINQ Query Expressions (C# Programming Guide)


Visual Studio 2010

Other Versions

• Visual Studio 2008

Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of
query capabilities directly into the C# language (also in Visual Basic and potentially any other .NET
language). With LINQ, a query is now a first-class language construct, just like classes, methods, events
and so on.
For a developer who writes queries, the most visible "language-integrated" part of LINQ is the query
expression. Query expressions are written in a declarative query syntax introduced in C# 3.0. By using
query syntax, you can perform even complex filtering, ordering, and grouping operations on data
sources with a minimum of code. You use the same basic query expression patterns to query and
transform data in SQL databases, ADO.NET Datasets, XML documents and streams, and .NET collections.
The following example shows the complete query operation. The complete operation includes creating a
data source, defining the query expression, and executing the query in a foreach statement.
Aishwarya Lakshmi 60
C# Notes

VB

C#

C++

F#

JScript

Copy

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;
Aishwarya Lakshmi 61
C# Notes

// Execute the query.

foreach (int i in scoreQuery)

Console.Write(i + " ");

// Output: 97 92 81

For more information about the basics of LINQ in C#, see Getting Started with LINQ in C#.

Query Expression Overview

• 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.
For more information, see Getting Started with LINQ in C#.
• 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. For more information, see Type
Relationships in LINQ Query Operations (C#).
• A query is not executed until you iterate over the query variable in a foreach statement. For more
information, see Introduction to LINQ Queries (C#).
• 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. For more information, see C# Language Specification and Standard
Query Operators Overview.
• As a rule when you write LINQ queries, we recommend that you use query syntax whenever
possible and method syntax whenever necessary. There is no semantic or performance difference
between the two different forms. Query expressions are often more readable than equivalent
expressions written in method syntax.
• Some query operations, such as Count or Max, have no equivalent query expression clause and
must therefore be expressed as a method call. Method syntax can be combined with query syntax
in various ways. For more information, see LINQ Query Syntax versus Method Syntax (C#).
• Query expressions can be compiled to expression trees or to delegates, depending on the type
that the query is applied to. IEnumerable<T> queries are compiled to delegates. IQueryable and
Aishwarya Lakshmi 62
C# Notes

IQueryable<T> queries are compiled to expression trees. For more information, see Expression
Trees (C# and Visual Basic).

Lambda Expressions (C# Programming Guide)


Visual Studio 2010

Other Versions

• Visual Studio 2008

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:

VB

C#

C++

F#

JScript

Copy

delegate int del(int i);


Aishwarya Lakshmi 63
C# Notes

static void Main(string[] args)

del myDelegate = x => x * x;

int j = myDelegate(5); //j = 25

To create an expression tree type:

VB

C#

C++

F#

JScript

Copy

using System.Linq.Expressions;

namespace ConsoleApplication1

class Program

static void Main(string[] args)

{
Aishwarya Lakshmi 64
C# Notes

Expression<del> myET = x => x * x;

The => operator has the same precedence as assignment (=) and is right-associative.
Lambdas are used in method-based LINQ queries as arguments to standard query operator methods
such as Where.
When you use method-based syntax to call the Where method in the Enumerable class (as you do in
LINQ to Objects and LINQ to XML) the parameter is a delegate type System.Func<T, TResult>. A lambda
expression is the most convenient way to create that delegate. When you call the same method in, for
example, the System.Linq.Queryable class (as you do in LINQ to SQL) then the parameter type is
an System.Linq.Expressions.Expression<Func> where Func is any Func delegates with up to sixteen
input parameters. Again, a lambda expression is just a very concise way to construct that expression
tree. The lambdas allow the Where calls to look similar although in fact the type of object created from
the lambda is different.
In the previous example, notice that the delegate signature has one implicitly-typed input parameter of
type int, and returns an int. The lambda expression can be converted to a delegate of that type because
it also has one input parameter (x) and a return value that the compiler can implicitly convert to type int.
(Type inference is discussed in more detail in the following sections.) When the delegate is invoked by
using an input parameter of 5, it returns a result of 25.
Lambdas are not allowed on the left side of the is or as operator.
All restrictions that apply to anonymous methods also apply to lambda expressions. For more
information, see Anonymous Methods (C# Programming Guide).

Expression Lambdas

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 (C# and Visual Basic). An
expression lambda returns the result of the expression and takes the following basic form:
Copy

(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:
Copy

(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:
Copy

(int x, string s) => s.Length > x

Specify zero input parameters with empty parentheses:


Aishwarya Lakshmi 65
C# Notes

Copy

() => SomeMethod()

Note in the previous example that the body of an expression lambda can consist of a method call.
However, if you are creating expression trees that will be consumed in another domain, such as SQL
Server, you should not use method calls in lambda expressions. The methods will have no meaning
outside the context of the .NET common language runtime.

Statement Lambdas

A statement lambda resembles an expression lambda except that the statement(s) is enclosed in braces:
Copy

(input parameters) => {statement;}

The body of a statement lambda can consist of any number of statements; however, in practice there
are typically no more than two or three.
Copy

delegate void TestDelegate(string s);

TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };

myDel("Hello");

Statement lambdas, like anonymous methods, cannot be used to create expression trees.

Lambdas with the Standard Query Operators

Many Standard query operators have an input parameter whose type is one of the Func<T, TResult>
family of generic delegates. The Func<T, TResult> delegates use type parameters to define the number
and type of input parameters, and the return type of the delegate. Func delegates are very useful for
encapsulating user-defined expressions that are applied to each element in a set of source data. For
example, consider the following delegate type:
Copy

public delegate TResult Func<TArg0, TResult>(TArg0 arg0)

The delegate can be instantiated as Func<int,bool> myFunc where int is an input parameter and bool is
the return value. The return value is always specified in the last type parameter. Func<int, string,
bool> defines a delegate with two input parameters, int and string, and a return type of bool. The
following Func delegate, when it is invoked, will return true or false to indicate whether the input
parameter is equal to 5:
Copy

Func<int, bool> myFunc = x => x == 5;


Aishwarya Lakshmi 66
C# Notes

bool result = myFunc(4); // returns false of course

You can also supply a lambda expression when the argument type is an Expression<Func>, for
example in the standard query operators that are defined in System.Linq.Queryable. When you specify
an Expression<Func> argument, the lambda will be compiled to an expression tree.
A standard query operator, the Count method, is shown here:
Copy

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

int oddNumbers = numbers.Count(n => n % 2 == 1);

The compiler can infer the type of the input parameter, or you can also specify it explicitly. This
particular lambda expression counts those integers (n) which when divided by two have a remainder of
1.
The following method will produce a sequence that contains all the elements in the numbers array that
are to the left of the 9, because that is the first number in the sequence that does not meet the
condition:
Copy

var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);

This example shows how to specify multiple input parameters by enclosing them in parentheses. The
method returns all the elements in the numbers array until a number is encountered whose value is less
than its position. Do not confuse the lambda operator (=>) with the greater than or equal operator (>=).
Copy

var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

Type Inference in Lambdas

When writing lambdas, you often do not have to specify a type for the input parameters because the
compiler can infer the type based on the lambda body, the underlying delegate type, and other factors
as described in the C# Language Specification. For most of the standard query operators, the first input
is the type of the elements in the source sequence. So if you are querying an
IEnumerable<Customer>, then the input variable is inferred to be a Customer object, which means
you have access to its methods and properties:
Copy

customers.Where(c => c.City == "London");

The general rules for lambdas are as follows:


• The lambda must contain the same number of parameters as the delegate type.
• Each input parameter in the lambda must be implicitly convertible to its corresponding delegate
parameter.
• The return value of the lambda (if any) must be implicitly convertible to the delegate's return type.
Note that lambda expressions in themselves do not have a type because the common type system has
no intrinsic concept of "lambda expression." However, it is sometimes convenient to speak informally of
the "type" of a lambda expression. In these cases the type refers to the delegate type or Expression type
to which the lambda expression is converted.
Aishwarya Lakshmi 67
C# Notes

Variable Scope in Lambda Expressions

Lambdas can refer to outer variables that are in scope in the enclosing method or type in which the
lambda is defined. Variables that are captured in this manner are stored for use in the lambda
expression even if variables would otherwise go out of scope and be garbage collected. An outer variable
must be definitely assigned before it can be consumed in a lambda expression. The following example
demonstrates these rules:
Copy

delegate bool D();

delegate bool D2(int i);

class Test

D del;

D2 del2;

public void TestMethod(int input)

int j = 0;

// Initialize the delegates with lambda expressions.

// Note access to 2 outer variables.

// del will be invoked within this method.

del = () => { j = 10; return j > input; };

// del2 will be invoked after TestMethod goes out of scope.

del2 = (x) => {return x == j; };

// Demonstrate value of j:

// Output: j = 0

// The delegate has not been invoked yet.

Console.WriteLine("j = {0}", j); // Invoke the delegate.


Aishwarya Lakshmi 68
C# Notes

bool boolResult = del();

// Output: j = 10 b = True

Console.WriteLine("j = {0}. b = {1}", j, boolResult);

static void Main()

Test test = new Test();

test.TestMethod(5);

// Prove that del2 still has a copy of

// local variable j from TestMethod.

bool result = test.del2(10);

// Output: True

Console.WriteLine(result);

Console.ReadKey();

The following rules apply to variable scope in lambda expressions:


• A variable that is captured will not be garbage-collected until the delegate that references it goes
out of scope.
• Variables introduced within a lambda expression are not visible in the outer method.
• A lambda expression cannot directly capture a ref or out parameter from an enclosing method.
• A return statement in a lambda expression does not cause the enclosing method to return.
• A lambda expression cannot contain a goto statement, break statement, or continue statement
whose target is outside the body or in the body of a contained anonymous function.
Aishwarya Lakshmi 69
C# Notes

You might also like