Thursday, July 9, 2009

Indexers

1.Indexers enable objects to be indexed in a similar way to arrays.
2.A get accessor returns a value. A set accessor assigns a value.
3.The
this keyword is used to define the indexers.
4.The
value keyword is used to define the value being assigned by the set indexer.
5.Indexers do not have to be indexed by an integer value; it is up to you how to define the specific look-up mechanism.
6.Indexers can be overloaded.
7.Indexers can have more than one formal parameter, for example, when accessing a two-dimensional array.
Indexers allow you to index a
class, struct, or interface in the same way as an array. For more information about using indexers with an interface, see Interface Indexers.
To declare an indexer on a class or struct, use the
this keyword, as in this example:
public int this[int index] // Indexer declaration
{
// get and set accessors
}
The type of an indexer and the type of its parameters must be at least as accessible as the indexer itself. For more information about accessibility levels, see Access Modifiers.
The signature of an indexer consists of the number and types of its formal parameters. It does not include the indexer type or the names of the formal parameters. If you declare more than one indexer in the same class, they must have different signatures.
An indexer value is not classified as a variable; therefore, it is not possible to pass an indexer value as a
ref or out parameter.
To provide the indexer with a name that other languages can use, use a name attribute in the declaration. For example:
[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this [int index] // Indexer declaration
{
}
This indexer will have the name TheItem. Not providing the name attribute would make Item the default name.
Example 1
The following example shows how to declare a private array field, arr, and an indexer. Using the indexer enables direct access to the instance test[i]. The alternative to using the indexer is to declare the array as a
public member and access its members, arr[i], directly.
C#
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
// Auto-Implemented Property
System.DateTime date { get; set; }
// To enable client code to validate input
// when accessing your indexer.
public int Length
{
get { return temps.Length; }
}
// Indexer declaration.
// Input parameter is validated by client
// code before being passed to the indexer.
public float this[int index]
{
get
{
return temps[index];
}

set
{
temps[index] = value;
}
}
}

class MainClass
{
static void Main()
{
TempRecord tempRecord = new TempRecord();
// Use the indexer's set accessor
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;

// Use the indexer's get accessor
for (int i = 0; i < 10; i++)
{
// This example validates the input on the client side. You may
// choose to validate it in the class that implements the indexer, and throw an
// exception or return an error code in the case of invalid input.
if (i < tempRecord.Length)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
else
{
System.Console.WriteLine("Index value of {0} is out of range", i);
}
}

//Uncomment this code to see how the .NET Framework handles indexer exceptions
//try
//{
// System.Console.WriteLine("Element #{0} = {1}", tempRecord[tempRecord.Length]);
//}
//catch (System.ArgumentOutOfRangeException e)
//{
// System.Console.WriteLine(e);
//}
}
}
Output
Element #0 = 0
Element #1 = 0
Element #2 = 0
Element #3 = 256
Element #4 = 0
Element #5 = 1024
Element #6 = 0
Element #7 = 0
Element #8 = 0
Element #9 = 0
Element #10 = 0
Notice that when an indexer's access is evaluated, for example, in a Console.Write statement, the
get accessor is invoked. Therefore, if no get accessor exists, a compile-time error occurs.

Friday, June 19, 2009

C# Members

Members (C# Programming Guide)
Classes and structs have members that represent their data and behavior. Those members include:
Fields (C# Programming Guide)
Fields are instances of objects that are considered part of a class, normally holding class data. For example, a calendar class may have a field that contains the current date.
Properties (C# Programming Guide)
Properties are methods on a class that are accessed as if they were fields on that class. A property can provide protection for a class field to keep it from being changed without the object's knowledge.
Methods (C# Programming Guide)
Methods define the actions that a class can perform. Method can take parameters that provide input data, and can return output data through parameters. Methods can also return a value directly, without using a parameter.
Events (C# Programming Guide)
Events are a way of providing notifications about occurrences, such as button clicks or the successful completion of a method, to other objects. Events are defined and triggered using delegates. For more information, see
Events and Delegates.
Operators (C# Programming Guide)
Operators are terms or symbols such as +, *, <, and so on that perform operations on operands. Operators can be redefined to perform operations on custom data types. For more information, see
Overloadable Operators (C# Programming Guide).
Indexers (C# Programming Guide)
Indexers allow an object to be indexed in a manner similar to arrays.
Constructors (C# Programming Guide)
Constructors are methods that are called when the object is first created. They are often used to initialize the object's data.
Destructors (C# Programming Guide)
Destructors are methods that are called by the runtime execution engine when the object is about to be removed from memory. They are generally used to make sure that any resources which need to be released are handled appropriately.
Nested Types (C# Programming Guide)
Nested Types are types declared within a class or struct. Nested Types are often used to describe objects used only by the types containing them.

OOPS - Interfaces

Interfaces Overview
An interface has the following properties:
An interface is similar to an abstract base class: any non-abstract type inheriting the interface must implement all its members.
An interface cannot be instantiated directly.
Interfaces can contain events, indexers, methods and properties.
Interfaces contain no implementation of methods.
Classes and structs can inherit from more than one interface.
An interface can itself inherit from multiple interfaces.
Explicit Interface Implementation (C# Programming Guide)
If a
class implements two interfaces that contain a member with the same signature, then implementing that member on the class will cause both interfaces to use that member as their implementation. For example:
C#
Interface IControl
{
void Paint();
}
interface ISurface
{
void Paint();
}
class SampleClass : IControl, ISurface
{
// Both ISurface.Paint and IControl.Paint call this method.
public void Paint()
{
}
}
If the two
interface members do not perform the same function, however, this can lead to an incorrect implementation of one or both of the interfaces. It is possible to implement an interface member explicitly—creating a class member that is only called through the interface, and is specific to that interface. This is accomplished by naming the class member with the name of the interface and a period. For example:
C#
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
The class member IControl.Paint is only available through the IControl interface, and ISurface.Paint is only available through ISurface. Both method implementations are separate, and neither is available directly on the class. For example:
C#
SampleClass obj = new SampleClass();
//obj.Paint(); // Compiler error.

IControl c = (IControl)obj;
c.Paint(); // Calls IControl.Paint on SampleClass.

ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.
Explicit implementation is also used to resolve cases where two interfaces each declare different members of the same name such as a property and a method:
C#
interface ILeft
{
int P { get;}
}
interface IRight
{
int P();
}

OOPS - Polymorphism

Polymorphism
The ability for an object to represent more than one type is called polymorphism.
When a derived class inherits from a base class, it gains all the methods, fields, properties and events of the base class. To change the data and behavior of a base class, you have two choices: you can replace the base member with a new derived member, or you can override a virtual base member.
Replacing a member of a base class with a new derived member requires the
new keyword. If a base class defines a method, field, or property, the new keyword is used to create a new definition of that method, field, or property on a derived class. The new keyword is placed before the return type of a class member that is being replaced. For example:
public class BaseClass
{
public void DoWork()
{ }
public int WorkField;
public int WorkProperty
{ get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork()
{ }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
When the new keyword is used, the new class members are called instead of the base class members that have been replaced. Those base class members are called hidden members. Hidden class members can still be called if an instance of the derived class is cast to an instance of the base class. For example:
DerivedClass B = new DerivedClass();B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;A.DoWork(); // Calls the old method.
In order for an instance of a derived class to completely take over a class member from a base class, the base class has to declare that member as virtual. This is accomplished by adding the virtual keyword before the return type of the member. A derived class then has the option of using the override keyword, instead of new, to replace the base class implementation with its own.
For example:
public class BaseClass
{
public virtual void DoWork()
{ }
public virtual int WorkProperty
{ get { return 0; } }
}
public class DerivedClass : BaseClass
{
public override void DoWork()
{ }
public override int WorkProperty
{ get { return 0; } }
}
Fields cannot be virtual; only methods, properties, events and indexers can be virtual. When a derived class overrides a virtual member, that member is called even when an instance of that class is being accessed as an instance of the base class. For example:
C#

DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
Virtual methods and properties allow you to plan ahead for future expansion. Because a virtual member is called regardless of which type the caller is using, it gives derived classes the option to completely change the apparent behavior of the base class.
Virtual members remain virtual indefinitely, no matter how many classes have been declared between the class that originally declared the virtual member. If class A declares a virtual member, and class B derives from A, and class C derives from B, class C inherits the virtual member, and has the option to override it, regardless of whether class B declared an override for that member. For example:
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
C#
public class C : B
{
public override void DoWork() { }
}

A derived class can stop virtual inheritance by declaring an override as sealed. This requires putting the
sealed keyword before the override keyword in the class member declaration. For example:
C#
public class C : B
{
public sealed override void DoWork() { }
}
In the previous example, the method DoWork is no longer virtual to any class derived from C. It is still virtual for instances of C, even if they are cast to type B or type A. Sealed methods can be replaced by derived classes using the new keyword, as the following example shows:
C#
public class D : C
{
public new void DoWork() { }
}
In this case, if DoWork is called on D using a variable of type D, the new DoWork is called. If a variable of type C, B, or A is used to access an instance of D, a call to DoWork will follow the rules of virtual inheritance, routing those calls to the implementation of DoWork on class C.
A derived class that has replaced or overridden a method or property can still access the method or property on the base class using the base keyword. For example:
C#
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
C#
public class C : B
{
public override void DoWork()
{
// Call DoWork on B to get B's behavior:
base.DoWork();

// DoWork behavior specific to C goes here:
// ...
}
}


Versioning with the Override and New Keywords (C# Programming Guide):
The C# language is designed so that versioning between
base and derived classes in different libraries can evolve and maintain backwards compatibility. This means, for example, that the introduction of a new member in a base class with the same name as a member in a derived class is completely supported by C# and does not lead to unexpected behavior. It also means that a class must explicitly state whether a method is intended to override an inherited method, or whether a method is a new method that simply hides a similarly named inherited method.
C# allows derived classes to contain methods with the same name as base class methods.
The base class method must be defined
virtual.
If the method in the derived class is not preceded by
new or override keywords, the compiler will issue a warning and the method will behave as if the new keyword were present.
If the method in the derived class is preceded with the new keyword, the method is defined as being independent of the method in the base class.
If the method in the derived class is preceded with the override keyword, objects of the derived class will call that method rather than the base class method.
The base class method can be called from within the derived class using the base keyword.
The override, virtual, and new keywords can also be applied to properties, indexers, and events.
By default, C# methods are not virtual — if a method is declared as virtual, any class inheriting the method can implement its own version. To make a method virtual, the virtual modifier is used in the method declaration of the base class. The derived class can then override the base virtual method by using the override keyword or hide the virtual method in the base class by using the new keyword. If neither the override keyword nor the new keyword is specified, the compiler will issue a warning and the method in the derived class will hide the method in the base class. For more information, see
Compiler Warning CS0108.
To demonstrate this in practice, assume for a moment that Company A has created a class entitled GraphicsClass, which your program uses. GraphicsClass looks like this:
C#

class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
Your company uses this class, and you use it to derive your own class, adding a new method:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
Your application is used without problems, until Company A releases a new version of GraphicsClass, which looks like this:
C#
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
The new version of GraphicsClass now contains a method entitled DrawRectangle. Initially, nothing happens. The new version is still binary compatible with the old — any software you have deployed will continue to work, even if the new class is installed on those computer systems. Any existing calls to the method DrawRectangle will continue to reference your version, in your derived class.
However, once you recompile your application using the new version of GraphicsClass, you will receive a warning from the compiler. For more information, see
Compiler Warning CS0108.
This warning informs you that you need to consider how you want your DrawRectangle method to behave in your application.
If you want your method to override the new base class method, use the override keyword, like this:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
The override keyword makes sure that any objects derived from YourDerivedGraphicsClass will use the derived class version of DrawRectangle. Objects derived from YourDerivedGraphicsClass can still access the base class version of DrawRectangle using the base keyword, like this:
C#
base.DrawRectangle();
If you do not want your method to override the new base class method, the following considerations apply.To avoid confusion between the two methods, you can rename your method. This can be time-consuming and error-prone, and simply not practical in some situations. However, if your project is relatively small, you can use Visual Studio's Refactoring options to rename the method. For more information, see
Refactoring Classes and Types.
Alternatively, you can prevent the warning by using the keyword new in your derived class definition, like this:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
Using the new keyword tells the compiler that your definition hides the definition contained in the base class. This is the default behavior.
Override and Method Selection
When a method is named on a class, the C# compiler selects the best method to call if more than one method is compatible with the call, such as when there are two methods with the same name, and parameters that are compatible with the parameter passed. The following methods would be compatible:
C#
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
When DoWork is called on an instance of Derived, the C# compiler will first try to make the call compatible with the versions of DoWork declared originally on Derived. Override methods are not considered as declared on a class, they are new implementations of a method declared on a base class. Only if the C# compiler cannot match the method call to an original method on Derived will it try to match the call to an overridden method with the same name and compatible parameters. For example:
C#
int val = 5;
Derived d = new Derived();
d.DoWork(val); // Calls DoWork(double).
Because the variable val can be converted to a double implicitly, the C# compiler calls DoWork(double) instead of DoWork(int). There are two ways to avoid this. First, avoid declaring new methods with the same name as virtual methods. Second, you can instruct the C# compiler to call the virtual method by making it search the base class method list by casting the instance of Derived to Base. Because the method is virtual, the implementation of DoWork(int) on Derived will be called. For example:
C#
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.

Knowing When to Use Override and New Keywords (C# Programming Guide)
C# enables methods in derived classes to have the same name as methods in base classes—as long as you are very specific about how the new method should be treated. The following example demonstrates the use of the
new and override keywords.
First we declare three classes: a
base class called Car, and two classes that derive from it, ConvertibleCar and Minivan. The base class contains a single method, DescribeCar, which sends a description of the car to the console. The derived class methods also include a method called DescribeCar, which displays their unique properties. These methods also call the base class DescribeCar method to demonstrate how they have inherited the properties of the Car class.
In order to highlight the difference, the ConvertibleCar class is defined with the new keyword, while the Minivan class is defined with override.
C#
// Define the base class
class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
}
}

// Define the derived classes
class ConvertibleCar : Car
{
public new virtual void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("A roof that opens up.");
}
}

class Minivan : Car
{
public override void DescribeCar()
{
base.DescribeCar();
System.Console.WriteLine("Carries seven people.");
}
}
We can now write some code that declares instances of these classes, and calls their methods so that the objects can describe themselves:
C#
public static void TestCars1()
{
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------");

ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------");

Minivan car3 = new Minivan();
car3.DescribeCar();
System.Console.WriteLine("----------");
}
As you might expect, the output looks like this:
Four wheels and an engine.
----------
Four wheels and an engine.
A roof that opens up.
----------
Four wheels and an engine.
Carries seven people.
----------
However, in this next section of code, we declare an array of objects derived from the Car base class. This array can store Car, ConvertibleCar, and Minivan objects. The array is declared like this:
C#
public static void TestCars2()
{
Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new ConvertibleCar();
cars[2] = new Minivan();
}
We can then use a foreach loop to visit each Car object contained in the array, and call the DescribeCar method, like this:
C#
foreach (Car vehicle in cars)
{
System.Console.WriteLine("Car object: " + vehicle.GetType());
vehicle.DescribeCar();
System.Console.WriteLine("----------");
}
The output from this loop is as follows:
Car object: YourApplication.Car
Four wheels and an engine.
----------
Car object: YourApplication.ConvertibleCar
Four wheels and an engine.
----------
Car object: YourApplication.Minivan
Four wheels and an engine.
Carries seven people.
----------
Notice how the ConvertibleCar description is not what you might expect. As the new keyword was used to define this method, the derived class method is not called—the base class method is called instead. The Minivan object correctly calls the overridden method, producing the results we expected.
If you want to enforce a rule that all classes derived from Car must implement the DescribeCar method, you should create a new base class that defines the method DescribeCar as abstract. An abstract method does not contain any code, only the method signature. Any classes derived from this base class must provide an implementation of DescribeCar. For more information, see
abstract

OOPS - Part 2

Inheritance
Classes can inherit from another class. This is accomplished by putting a colon after the class name when declaring the class, and naming the class to inherit from—the base class—after the colon.
The new class—the derived class—then gains all the non-private data and behavior of the base class in addition to any other data or behaviors it defines for itself. The new class then has two effective types: the type of the new class and the type of the class it inherits.
Abstract Classes
The
abstract keyword enables you to create classes and class members solely for the purpose of inheritance—to define features of derived, non-abstract classes.
An abstract class cannot be instantiated. The purpose of an abstract class is to provide a common definition of a base class that multiple derived classes can share. For example, a class library may define an abstract class that is used as a parameter to many of its functions, and require programmers using that library to provide their own implementation of the class by creating a derived class.
Abstract classes may also define abstract methods. This is accomplished by adding the keyword abstract before the return type of the method. For example:
public abstract class A
{
public abstract void DoWork(int i);
}

Abstract methods have no implementation, so the method definition is followed by a semicolon instead of a normal method block. Derived classes of the abstract class must implement all abstract methods. When an abstract class inherits a virtual method from a base class, the abstract class can override the virtual method with an abstract method.

For example:
public class D
{
public virtual void DoWork(int i)
{ // Original implementation.
}
}
public abstract class E : D
{
public abstract override void DoWork(int i);
}
public class F : E
{ public override void DoWork(int i) { // New implementation. }
}
If a virtual method is declared abstract, it is still virtual to any class inheriting from the abstract class. A class inheriting an abstract method cannot access the original implementation of the method—in the previous example, DoWork on class F cannot call DoWork on class D. In this way, an abstract class can force derived classes to provide new method implementations for virtual methods.


Sealed Classes
Classes can be declared as sealed. This is accomplished by putting the keyword sealed before the keyword class in the class definition. For example:
public sealed class D
{
// Class members here.
}
A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class. Sealed classes are primarily used to prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster.
A class member, method, field, property, or event, on a derived class that is overriding a virtual member of the base class can declare that member as sealed. This negates the virtual aspect of the member for any further derived class. This is accomplished by putting the sealed keyword before the
override keyword in the class member declaration. For example:
public class D : C
{
public sealed override void DoWork()
{ }
}

OOPS - Part 1

Classes
A class is the most powerful data type in C#. Like structures, a class defines the data and behavior of the data type. Programmers can then create objects that are instances of this class. Unlike structures, classes support inheritance, a fundamental part of object-oriented programming. Classes are Template of an Object.
The class keyword is preceded by the access level. In this case
public is used, meaning anyone can create objects from this class. The name of the class follows the class keyword. The remainder of the definition is the class body, where the behavior and data are defined. Fields, properties, methods, and events on a class are collectively referred to as class members.
Objects
Objects are instance of a class and it’s a concrete Entity Objects are programming constructs that have data, behavior, and identity.
Object data is contained in the fields, properties, and events of the object, and object behaviors are defined by the methods and interfaces of the object. Objects have identity — two objects with the same set of data are not necessarily the same object.
Objects in C# are defined through classes and structs — these form the single blueprint from which all objects of that type operate.
Structs Overview
Structs are used for representing the light weight objects
Structs have the following properties:
Structs are value types while classes are reference types.
Unlike classes, structs can be instantiated without using a new operator.
Structs can declare constructors, but they must take parameters.
A struct cannot inherit from another struct or class, and it cannot be the base of a class. All structs inherit directly from System.ValueType, which inherits from System.Object.
A struct can implement interfaces.

Components in .Net

The basic components of .NET platform (framework) are mentioned in layers :
-------------------------------------------------------
.Net Applications
------------------------------------------------------
(Win Forms,Web Applications,Web Services)

------------------------------------------------------
Data(ADO.Net) and XML Library

------------------------------------------------------
FrameWork Class Library(FCL)

(IO,Streams,Sockets,Security,Reflection,UI)
------------------------------------------------------
Common Language Runtime(CLR)
(Debugger,Type Checker,JITer,GC)

------------------------------------------------------
Operating System
(Windows,Linux,UNIX,Macintosh,etc.,)

------------------------------------------------------
Common Language Runtime (CLR):
The most important part of the .NET Framework is the .Net Common Language Runtime (CLR) also called .Net Runtime in short. It is a framework layer that resides above the Operating System and handles/manages the execution of the .NET applications. Our .Net programs don't directly communicate with the Operating System but through CLR.
MSIL (Microsoft Intermediate Language) Code:
When we compile our .Net Program using any .Net compliant language like (C#, VB.NET, C++.NET) it does not get converted into the executable binary code but to an intermediate code, called MSIL or IL in short, understandable by CLR. MSIL is an OS and H/w independent code. When the program needs to be executed, this MSIL or intermediate code is converted to binary executable code, called native code. The presence of IL makes it possible the Cross Language Relationship as all the .Net compliant languages produce the similar standard IL code.
Just In Time Compilers (JITers):
When our IL compiled code needs to be executed, CLR invokes JIT compilers which compile the IL code to native executable code (.exe or .dll) for the specific machine and OS. JITers in many ways are different from traditional compilers as they, as their name suggests, compile the IL to native code only when desired e.g., when a function is called, IL of function's body is converted to native code; just in time of need. So, the part of code that is not used by particular run is not converted to native code. If some IL code is converted to native code then the next time when its needed to be used, the CLR uses the same copy without re-compiling. So, if a program runs for sometime, then it won't have any just in time performance penalty. As JITers are aware of processor and OS exactly at runtime, they can optimize the code extremely efficiently resulting in very robust applications. Also, since JITer knows the exact current state of executable code, they can also optimize the code by in-lining small function calls (like replacing body of small function when its called in a loop, saving the function call time). Although, Microsoft stated that C# and .Net are not competing with languages like C++ in efficiency, speed of execution, JITers can make your code even faster than C++ code in some cases when program is run over extended period of time (like web-servers).
Framework Class Library (FCL):
.NET Framework provides huge set of Framework (or Base) Class Library (FCL) for common, usual tasks. FCL contains thousands of classes to provide the access to Windows API and common functions like String Manipulation, Common Data Structures, IO, Streams, Threads, Security, Network Programming, Windows Programming, Web Programming, Data Access, etc. It is simply the largest standard library ever shipped with any development environment or programming language. The best part of this library is they follow extremely efficient OO design (design patterns) making their access and use very simple and predictable. You can use the classes in FCL in your program just as you use any other class and can even apply inheritance and polymorphism on these.
Common Language Specification (CLS):
Earlier we used the term '.NET Compliant Language' and stated that all the .NET compliant languages can make use of CLR and FCL. But what makes a language '.NET compliant language'? The answer is Common Language Specification (CLS). Microsoft has released a small set of specification that each language should meet to qualify as a .NET Compliant Language. As IL is a very rich language, it is not necessary for a language to implement all the IL functionality, rather it meets the small subset of it, CLS, to qualify as a .NET compliant language, which is the reason why so many languages (procedural and OO) are now running under .Net umbrella. CLS basically addresses to language design issues and lays certain standards like there should be no global function declaration, no pointers, no multiple inheritance and things like that. The important point to note here is that if you keep your code within CLS boundary, your code is guaranteed to be usable in any other .Net language.
Common Type System (CTS):
.NET also defines a Common Type System (CTS). Like CLS, CTS is also a set of standards. CTS defines the basic data types that IL understands. Each .NET compliant language should map its data types to these standard data types. This makes it possible for the 2 languages to communicate with each other by passing/receiving parameters to/from each other. For example, CTS defines a type Int32, an integral data type of 32 bits (4 bytes) which is mapped by C# through int and VB.Net through its Integer data type.
Garbage Collector (GC):
CLR also contains Garbage Collector (GC) which runs in a low-priority thread and checks for un-referenced dynamically allocated memory space. If it finds some data that is no more referenced by any variable/reference, it re-claims it and returns the occupied memory back to the Operating System; so that it can be used by other programs as necessary. The presence of standard Garbage Collector frees the programmer from keeping track of dangling data.