Pixytech

Lead Architect  •  Full Stack Engineer

Year: 2010

  • C# Reference

    C# Keywords

    Keywords are predefined, reserved identifiers that have special meanings to the compiler. They cannot be used as identifiers in your program unless they include @ as a prefix. For example, @if is a valid identifier but if is not because if is a keyword.

    The first table in this topic lists keywords that are reserved identifiers in any part of a C# program. The second table in this topic lists the contextual keywords in C#. Contextual keywords have special meaning only in a limited program context and can be used as identifiers outside that context. Generally, as new keywords are added to the C# language, they are added as contextual keywords in order to avoid breaking programs written in earlier versions.

    So here we goes to quickly review your C# skills. you may click on links to dig more into keywords implementation on msdn. press back button to continue from msdn.

    Keywords Description
    abstract The abstract modifier indicates that the thing being modified has a missing or incomplete implementation. The abstract modifier can be used with classes, methods, properties, indexers, and events. Use the abstract modifier in a class declaration to indicate that a class is intended only to be a base class of other classes. Members marked as abstract, or included in an abstract class, must be implemented by classes that derive from the abstract class.
    as The as operator is used to perform certain types of conversions between compatible reference types.
    base The base keyword is used to access members of the base class from within a derived class:

    • Call a method on the base class that has been overridden by another method.
    • Specify which base-class constructor should be called when creating instances of the derived class.

    A base class access is permitted only in a constructor, an instance method, or an instance property accessor.

    It is an error to use the base keyword from within a static method.

    The base class that is accessed is the base class specified in the class declaration. For example, if you specify class ClassB : ClassA, the members of ClassA are accessed from ClassB, regardless of the base class of ClassA.

    bool The bool keyword is an alias of System.Boolean. It is used to declare variables to store the Boolean values, true and false.If you require a Boolean variable that can also have a value of null, use bool? For more information, see Nullable Types (C# Programming Guide).
    break The break statement terminates the closest enclosing loop or switch statement in which it appears. Control is passed to the statement that follows the terminated statement, if any.
    byte The byte keyword denotes an integral type that stores values (0 to 255) as Unsigned 8-bit integer
    case The switch statement is a control statement that selects a switch section to execute from a list of candidates.Each switch section contains one or more case labels and a list of one or more statements.
    catch The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions. When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. If the currently executing method does not contain such a catch block, the CLR looks at the method that called the current method, and so on up the call stack. If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.
    char The char keyword is used to declare a Unicode character in the range U+0000 to U+ffff. Unicode characters are 16-bit characters that are used to represent most of the known written languages throughout the world.
    checked The checked keyword is used to explicitly enable overflow checking for integral-type arithmetic operations and conversions.By default, an expression that contains only constant values causes a compiler error if the expression produces a value that is outside the range of the destination type. If the expression contains one or more non-constant values, the compiler does not detect the overflow.By default, the non-constant expressions are not checked for overflow at run time either, and they do not raise overflow exceptions. Overflow checking can be enabled by compiler options, environment configuration, or use of the checked keyword.// Checked expression.Console.WriteLine(checked(2147483647 + ten));
    class Classes are declared using the keyword class. Unlike C++, only single inheritance is allowed in C#. In other words, a class can inherit implementation from one base class only. However, a class can implement more than one interface (multiple interface inheritance). The access levels protected and private are only allowed on nested classes. You can also declare generic classes that have type parameters; see Generic Classes for more information.A class can contain declarations of the following members:

    Constructors Whenever a class or struct is created, its constructor is called. A class or struct may have multiple constructors that take different arguments. Constructors enable the programmer to set default values, limit instantiation, and write code that is flexible and easy to read.If you do not provide a constructor for your object, C# will create one by default that instantiates the object and sets member variables to the default values as listed in Default Values Table (C# Reference). Static classes and structs can also have constructors.
    Destructors Destructors are used to destruct instances of classes.

    • Destructors cannot be defined in structs. They are only used with classes.
    • A class can only have one destructor.
    • Destructors cannot be inherited or overloaded.
    • Destructors cannot be called. They are invoked automatically.
    • A destructor does not take modifiers or have parameters.
    Constants Constants are immutable values which are known at compile time and do not change for the life of the program. Constants are declared with the const modifier. Only the C# built-in types (excluding System.Object) may be declared as const. For a list of the built-in types, see Built-In Types Table (C# Reference). User-defined types, including classes, structs, and arrays, cannot be const. Use the readonly modifier to create a class, struct, or array that is initialized one time at runtime (for example in a constructor) and thereafter cannot be changed.Constants must be initialized as they are declared.
    Fields A field is a variable of any type that is declared directly in a class or struct. Fields are members of their containing type.A class or struct may have instance fields or static fields or both. Instance fields are specific to an instance of a type. If you have a class T, with an instance field F, you can create two objects of type T, and modify the value of F in each object without affecting the value in the other object. By contrast, a static field belongs to the class itself, and is shared among all instances of that class. Changes made from instance A will be visibly immediately to instances B and C if they access the field.Generally, you should use fields only for variables that have private or protected accessibility. Data that your class exposes to client code should be provided through methods, properties and indexers. By using these constructs for indirect access to internal fields, you can guard against invalid input values. A private field that stores the data exposed by a public property is called a backing store or backing field.Fields typically store the data that must be accessible to more than one class method and must be stored for longer than the lifetime of any single method. For example, a class that represents a calendar date might have three integer fields: one for the month, one for the day, and one for the year. Variables that are not used outside the scope of a single method should be declared as local variables within the method body itself.Fields are declared in the class block by specifying the access level of the field, followed by the type of the field
    Methods A method is a code block that contains a series of statements. A program causes the statements to be executed by calling the method and specifying any required method arguments. In C#, every executed instruction is performed in the context of a method. The Main method is the entry point for every C# application and it is called by the common language runtime (CLR) when the program is started.Methods are declared in a class or struct by specifying the access level such as public or private, optional modifiers such as abstract or sealed, the return value, the name of the method, and any method parameters. These parts together are the signature of the method.A return type of a method is not part of the signature of the method for the purposes of method overloading. However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.By default, when a value type is passed to a method, a copy is passed instead of the object itself. Therefore, changes to the argument have no effect on the original copy in the calling method. You can pass a value-type by reference by using the ref keyword.Reference types are passed by reference. When an object of a reference type is passed to a method, the reference points to the original object, not a copy. Changes made through this reference will therefore be reflected in the calling method.Methods can return a value to the caller. If the return type, the type listed before the method name, is not void, the method can return the value by using the return keyword. A statement with the return keyword followed by a value that matches the return type will return that value to the method caller. The return keyword also stops the execution of the method. If the return type is void, a return statement without a value is still useful to stop the execution of the method. Without the return keyword, the method will stop executing when it reaches the end of the code block. Methods with a non-void return type are required to use the return keyword to return a value.
    Properties Properties are members that provide a flexible mechanism to read, write, or compute the values of private fields. Properties can be used as if they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily and still helps promote the safety and flexibility of methods.
    Indexers Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
    Operators In C#, an operator is a program element that is applied to one or more operands in an expression or statement. Operators that take one operand, such as the increment operator (++) or new, are referred to as unary operators. Operators that take two operands, such as arithmetic operators (+,-,*,/), are referred to as binary operators. One operator, the conditional operator (?:), takes three operands and is the sole ternary operator in C#.
    Events Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.Events have the following properties:

    • The publisher determines when an event is raised; the subscribers determine what action is taken in response to the event.
    • An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers.
    • Events that have no subscribers are never raised.
    • Events are typically used to signal user actions such as button clicks or menu selections in graphical user interfaces.
    • When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised. To invoke events asynchronously, see Calling Synchronous Methods Asynchronously.
    • Events can be used to synchronize threads.
    • In the .NET Framework class library, events are based on the EventHandler delegate and the EventArgs base class.
    Delegates A delegate is a type that defines a method signature. When you instantiate a delegate, you can associate its instance with any method with a compatible signature. You can invoke (or call) the method through the delegate instance.Delegates are used to pass methods as arguments to other methods. Event handlers are nothing more than methods that are invoked through delegates. You create a custom method and a class such as a windows control can call your method when a certain event occurs.Any method from any accessible class or struct that matches the delegate’s signature, which consists of the return type and parameters, can be assigned to the delegate. The method can be either static or an instance method. This makes it possible to programmatically change method calls, and also plug new code into existing classes. As long as you know the signature of the delegate, you can assign your own method.In the context of method overloading, the signature of a method does not include the return value. But in the context of delegates, the signature does include the return value. In other words, a method must have the same return value as the delegate.Delegates have the following properties:

    • Delegates are like C++ function pointers but are type safe.
    • Delegates allow methods to be passed as parameters.
    • Delegates can be used to define callback methods.
    • Delegates can be chained together; for example, multiple methods can be called on a single event.
    • Methods do not have to match the delegate signature exactly. For more information, see Using Variance in Delegates (C# and Visual Basic).
    • C# version 2.0 introduced the concept of Anonymous Methods, which allow code blocks to be passed as parameters in place of a separately defined method. C# 3.0 introduced lambda expressions as a more concise way of writing inline code blocks. Both anonymous methods and lambda expressions (in certain contexts) are compiled to delegate types. Together, these features are now known as anonymous functions. For more information about lambda expressions, see Anonymous Functions (C# Programming Guide).
    Classes A class is a construct that enables you to create your own custom types by grouping together variables of other types, methods and events. A class is like a blueprint. It defines the data and behavior of a type. If the class is not declared as static, client code can use it by creating objects or instances which are assigned to a variable. The variable remains in memory until all references to it go out of scope. At that time, the CLR marks it as eligible for garbage collection. If the class is declared as static, then only one copy exists in memory and client code can only access it through the class itself, not an instance variable.
    Interfaces Interfaces describe a group of related functionalities that can belong to any class or struct. Interfaces can consist of methods, properties, events, indexers, or any combination of those four member types. An interface cannot contain fields. Interfaces members are automatically public.When a class or struct is said to inherit an interface, it means that the class or struct provides an implementation for all of the members defined by the interface. The interface itself provides no functionality that a class or struct can inherit in the way that base class functionality can be inherited. However, if a base class implements an interface, the derived class inherits that implementation.Classes and structs can inherit from interfaces in a manner similar to how classes can inherit a base class or struct, with two exceptions:

    • A class or struct can inherit more than one interface.
    • When a class or struct inherits an interface, it inherits only the method names and signatures, because the interface itself contains no implementations.

    To implement an interface member, the corresponding member on the class must be public, non-static, and have the same name and signature as the interface member. Properties and indexers on a class can define extra accessors for a property or indexer defined on an interface. For example, an interface may declare a property with a get accessor, but the class implementing the interface can declare the same property with both a get and set accessor. However, if the property or indexer uses explicit implementation, the accessors must match.

    Interfaces and interface members are abstract; interfaces do not provide a default implementation.

    The IEquatable<T> interface announces to the user of the object that the object can determine whether it is equal to other objects of the same type, and the user of the interface does not have to know how this is implemented.

    Interfaces can inherit other interfaces. It is possible for a class to inherit an interface multiple times, through base classes or interfaces it inherits. In this case, the class can only implement the interface one time, if it is declared as part of the new class. If the inherited interface is not declared as part of the new class, its implementation is provided by the base class that declared it. It is possible for a base class to implement interface members using virtual members; in that case, the class inheriting the interface can change the interface behavior by overriding the virtual members. For more information about virtual members, see Polymorphism.

    An interface has the following properties:

    • An interface is like 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.
    Structs Structs share most of the same syntax as classes, although structs are more limited than classes:

    • Within a struct declaration, fields cannot be initialized unless they are declared as const or static.
    • A struct may not declare a default constructor (a constructor without parameters) or a destructor.
    • Structs are copied on assignment. When a struct is assigned to a new variable, all the data is copied, and any modification to the new copy does not change the data for the original copy. This is important to remember when working with collections of value types such as Dictionary<string, myStruct>.
    • Structs are value types and classes are reference types.
    • Unlike classes, structs can be instantiated without using a new operator.
    • Structs can declare constructors that have 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.
    • A struct can be used as a nullable type and can be assigned a null value.
    const The const keyword is used to modify a declaration of a field or local variable. It specifies that the value of the field or the local variable is constant, which means it cannot be modified.The readonly keyword differs from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, although a const field is a compile-time constant, the readonly field can be used for run-time constants, as in this line: public static readonly uint l1 = (uint)DateTime.Now.Ticks;
    continue The continue statement passes control to the next iteration of the enclosing iteration statement in which it appears.
    decimal The decimal keyword indicates a 128-bit data type. Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations.Approximate Range: (-7.9 x 1028 to 7.9 x 1028) / (100 to 28)Precision: 28-29 significant digits.
       
    default The default keyword.The default keyword can be used in the switch statement or in generic code:

    • The switch statement: Specifies the default label.
    • Generic code: Specifies the default value of the type parameter. This will be null for reference types and zero for value types.
    delegate The declaration of a delegate type is similar to a method signature. It has a return value and any number of parameters of any type.A delegate is a reference type that can be used to encapsulate a named or an anonymous method. Delegates are similar to function pointers in C++; however, delegates are type-safe and secure. For applications of delegates, see Delegates and Generic Delegates.Delegates are the basis for Events.A delegate can be instantiated by associating it either with a named or anonymous method. For more information, see Named Methods and Anonymous Methods.The delegate must be instantiated with a method or lambda expression that has a compatible return type and input parameters. For more information on the degree of variance that is allowed in the method signature, see Variance in Delegates (C# and Visual Basic). For use with anonymous methods, the delegate and the code to be associated with it are declared together.
    do The do statement executes a statement or a block of statements enclosed in {} repeatedly until a specified expression evaluates to false.
    double The double keyword signifies a simple type that stores 64-bit floating-point valuesApproximate Range: ±5.0 × 10−324 to ±1.7 × 10308Precision: 15-16 digits.
    else The if statement selects a statement for execution based on the value of a Boolean expression. In case result is false, else block will be executed.
    enum The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list.Usually it is best to define an enum directly within a namespace so that all classes in the namespace can access it with equal convenience. However, an enum can also be nested within a class or struct.By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.
    event The event keyword is used to declare an event in a publisher class.public class SampleEventArgs{public SampleEventArgs(string s) { Text = s; }public String Text {get; private set;} // readonly}

    public class Publisher

    {

    // Declare the delegate (if using non-generic pattern).

    public delegate void SampleEventHandler(object sender, SampleEventArgs e);

    // Declare the event.

    public event SampleEventHandler SampleEvent;

    // Wrap the event in a protected virtual method

    // to enable derived classes to raise the event.

    protected virtual void RaiseSampleEvent()

    {

    // Raise the event by using the () operator.

    if (SampleEvent != null)

    SampleEvent(this, new SampleEventArgs(“Hello”));

    }

    }

    Events are a special kind of multicast delegate that can only be invoked from within the class or struct where they are declared (the publisher class). If other classes or structs subscribe to the event, their event handler methods will be called when the publisher class raises the event.

    Events can be marked as public, private, protected, internal, or protectedinternal. These access modifiers define how users of the class can access the event.

    explicit The explicit keyword declares a user-defined type conversion operator that must be invoked with a cast. For example, this operator converts from a class called Fahrenheit to a class called Celsius:// Must be defined inside a class called Farenheit:public static explicit operator Celsius(Fahrenheit f){return new Celsius((5.0f / 9.0f) * (f.degrees – 32));}

    This conversion operator can be invoked like this:

    Fahrenheit f = new Fahrenheit(100.0f);

    Console.Write(“{0} fahrenheit”, f.Degrees);

    Celsius c = (Celsius)f;

    The conversion operator converts from a source type to a target type. The source type provides the conversion operator. Unlike implicit conversion, explicit conversion operators must be invoked by means of a cast. If a conversion operation can cause exceptions or lose information, you should mark it explicit. This prevents the compiler from silently invoking the conversion operation with possibly unforeseen consequences.

    extern The extern modifier is used to declare a method that is implemented externally. A common use of the extern modifier is with the DllImport attribute when you are using Interop services to call into unmanaged code. In this case, the method must also be declared as static, as shown in the following example:[DllImport(“avifil32.dll”)]private static extern void AVIFileInit();The extern keyword can also define an external assembly alias, which makes it possible to reference different versions of the same component from within a single assembly. For more information, see extern alias (C# Reference).It is an error to use the abstract (C# Reference) and extern modifiers together to modify the same member. Using the extern modifier means that the method is implemented outside the C# code, whereas using the abstract modifier means that the method implementation is not provided in the class.
    false Used as an overloaded operator or as a literal:

    • false Operator : Returns the bool value true to indicate that an operand is false and returns false otherwise. Prior to C# 2.0, the true and false operators were used to create user-defined nullable value types that were compatible with types such as SqlBool. However, the language now provides built-in support for nullable value types, and whenever possible you should use those instead of overloading the true and false operators. For more information, see Nullable Types (C# Programming Guide).
    • false Literal : Represents the boolean value false.
    finally The finally block is useful for cleaning up any resources allocated in the try block as well as running any code that must execute even if there is an exception. Control is always passed to the finally block regardless of how the try block exits.Whereas catch is used to handle exceptions that occur in a statement block, finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited.
    fixed The fixed statement prevents the garbage collector from relocating a movable variable. The fixed statement is only permitted in an unsafe context. Fixed can also be used to create fixed size buffers.The fixed statement sets a pointer to a managed variable and “pins” that variable during the execution of the statement. Without fixed, pointers to movable managed variables would be of little use since garbage collection could relocate the variables unpredictably. The C# compiler only lets you assign a pointer to a managed variable in a fixed statement.unsafe static void TestMethod(){// assume class Point { public int x, y; }// pt is a managed variable, subject to garbage collection.

    Point pt = new Point();

    // Using fixed allows the address of pt members to be

    // taken, and “pins” pt so it isn’t relocated.

    fixed (int* p = &pt.x)

    {

    *p = 1;

    }

    }

    float The float keyword signifies a simple type that stores 32-bit floating-point values.float x = 3.5F;If you do not use the suffix in the previous declaration, you will get a compilation error because you are trying to store a double value into a float variable.
    for The for loop executes a statement or a block of statements repeatedly until a specified expression evaluates to false. The for loop is useful for iterating over arrays and for sequential processing.
    foreach The foreach statement repeats a group of embedded statements for each element in an array or an object collection that implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable<T> interface. The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.The embedded statements continue to execute for each element in the array or collection. After the iteration has been completed for all the elements in the collection, control is transferred to the next statement following the foreach block.At any point within the foreach block, you can break out of the loop by using the break keyword, or step to the next iteration in the loop by using the continue keyword.A foreach loop can also be exited by the goto, return, or throwstatements.
    goto The goto statement transfers the program control directly to a labeled statement.A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.The goto statement is also useful to get out of deeply nested loops.
    if The if statement selects a statement for execution based on the value of a Boolean expression.
    implicit The implicit keyword is used to declare an implicit user-defined type conversion operator. Use it to enable implicit conversions between a user-defined type and another type, if the conversion is guaranteed not to cause a loss of data.class Digit{public Digit(double d) { val = d; }public double val;// …other members

    // User-defined conversion from Digit to double

    public static implicit operator double(Digit d)

    {

    return d.val;

    }

    // User-defined conversion from double to Digit

    public static implicit operator Digit(double d)

    {

    return new Digit(d);

    }

    }

    Digit dig = new Digit(7);

    //This call invokes the implicit “double” operator

    double num = dig;

    //This call invokes the implicit “Digit” operator

    Digit dig2 = 12;

    in The foreach statement repeats a group of embedded statements for each element in an array or an object collection that implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable<T> interface. The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.The embedded statements continue to execute for each element in the array or collection. After the iteration has been completed for all the elements in the collection, control is transferred to the next statement following the foreach block.At any point within the foreach block, you can break out of the loop by using the break keyword, or step to the next iteration in the loop by using the continue keyword.A foreach loop can also be exited by the goto, return, or throwstatements.
    in (generic modifier) For generic type parameters, the in keyword specifies that the type parameter is contravariant. You can use the in keyword in generic interfaces and delegates.Contravariance enables you to use a less derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement variant interfaces and implicit conversion of delegate types. Covariance and contravariance in generic type parameters are supported for reference types, but they are not supported for value types.A type can be declared contravariant in a generic interface or delegate if it is used only as a type of method arguments and not used as a method return type. Ref and out parameters cannot be variant.An interface that has a contravariant type parameter allows its methods to accept arguments of less derived types than those specified by the interface type parameter. For example, because in .NET Framework 4, in the IComparer<T> interface, type T is contravariant, you can assign an object of the IComparer(Of Person) type to an object of the IComparer(Of Employee) type without using any special conversion methods if Person inherits Employee.A contravariant delegate can be assigned another delegate of the same type, but with a less derived generic type parameter.
    int The int keyword denotes an integral type that stores values according to the size (Signed 32-bit integer) and range (-2,147,483,648 to 2,147,483,647)
    interface An interface contains only the signatures of methods, properties, events or indexers. A class or struct that implements the interface must implement the members of the interface that are specified in the interface definition.An interface can be a member of a namespace or a class and can contain signatures of the following members:

    An interface can inherit from one or more base interfaces.

    When a base type list contains a base class and interfaces, the base class must come first in the list.

    A class that implements an interface can explicitly implement members of that interface. An explicitly implemented member cannot be accessed through a class instance, but only through an instance of the interface.

    For more details and code examples on explicit interface implementation, see Explicit Interface Implementation (C# Programming Guide). Or read below

    Explicit Interface :

    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.

    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.

    public class SampleClass : IControl, ISurface

    {

    void IControl.Paint()

    {

    System.Console.WriteLine(“IControl.Paint”);

    }

    void ISurface.Paint()

    {

    System.Console.WriteLine(“ISurface.Paint”);

    }

    }

    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:

    internal The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly.A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code. For example, a framework for building graphical user interfaces could provide Control and Form classes that cooperate by using members with internal access. Since these members are internal, they are not exposed to code that is using the framework.
    is Checks if an object is compatible with a given type.An is expression evaluates to true if the provided expression is non-null, and the provided object can be cast to the provided type without causing an exception to be thrown.The is keyword causes a compile-time warning if the expression is known to always be true or to always be false, but typically evaluates type compatibility at run time.The is operator cannot be overloaded.Note that the is operator only considers reference conversions, boxing conversions, and unboxing conversions. Other conversions, such as user-defined conversions, are not considered.Anonymous methods are not allowed on the left side of the is operator. This exception includes lambda expressions.
    lock The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. This statement takes the following form:Object thisLock = new Object();lock (thisLock){// Critical code section.}

    The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

    The lock keyword calls Enter at the start of the block and Exit at the end of the block.

    In general, avoid locking on a public type, or instances beyond your code’s control. The common constructs lock (this), lock (typeof (MyType)), and lock (“myLock”) violate this guideline:

    • lock (this) is a problem if the instance can be accessed publicly.
    • lock (typeof (MyType)) is a problem if MyType is publicly accessible.
    • lock(“myLock”) is a problem because any other code in the process using the same string, will share the same lock.

    Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.

    long The long keyword denotes an integral type that stores values according to the size (Signed 64-bit integer) and range (–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
    namespace The namespace keyword is used to declare a scope. This namespace scope lets you organize code and gives you a way to create globally unique types.Within a namespace, you can declare one or more of the following types:

    Whether or not you explicitly declare a namespace in a C# source file, the compiler adds a default namespace. This unnamed namespace, sometimes referred to as the global namespace, is present in every file. Any identifier in the global namespace is available for use in a named namespace.

    Namespaces implicitly have public access and this is not modifiable.

    new In C#, the new keyword can be used as an operator, a modifier, or a constraint.new OperatorUsed to create objects and invoke constructors.new ModifierUsed to hide an inherited member from a base class member.When used as a modifier, the new keyword explicitly hides a member inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base-class version. Although you can hide members without the use of the new modifier, the result is a warning. If you use new to explicitly hide a member, it suppresses this warning and documents the fact that the derived version is intended as a replacement.

    public class BaseC

    {

    public int x;

    public void Invoke() { }

    }

    public class DerivedC : BaseC

    {

    new public void Invoke() { }

    }

    new Constraint

    Used to restrict types that might be used as arguments for a type parameter in a generic declaration.

    The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract.

    Apply the new constraint to a type parameter when your generic class creates new instances of the type, as shown in the following example:

    class ItemFactory<T> where T : new()

    {

    public T GetNewItem()

    {

    return new T();

    }

    }

    null The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables. Ordinary value types cannot be null. However, C# 2.0 introduced nullable value types. See Nullable Types (C# Programming Guide).
    object The object type is an alias for Object in the .NET Framework. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object. You can assign values of any type to variables of type object. When a variable of a value type is converted to object, it is said to be boxed. When a variable of type object is converted to a value type, it is said to be unboxed.
    operator Use the operator keyword to overload a built-in operator or to provide a user-defined conversion in a class or struct declaration.
    out The out contextual keyword is used in two contexts:

    • parameter modifier in parameter lists : The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.

    generic type parameters in generic interfaces and delegates : For generic type parameters, the out keyword specifies that the type parameter is covariant. You can use the out keyword in generic interfaces and delegates.

    Covariance enables you to use a more derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement variant interfaces and implicit conversion of delegate types. Covariance and contravariance are supported for reference types, but they are not supported for value types.

    An interface that has a covariant type parameter enables its methods to return more derived types than those specified by the type parameter. For example, because in .NET Framework 4, in IEnumerable<T>, type T is covariant, you can assign an object of the IEnumerabe(Of String) type to an object of the IEnumerable(Of Object) type without using any special conversion methods.

    A covariant delegate can be assigned another delegate of the same type, but with a more derived generic type parameter.

    For more information, see Covariance and Contravariance (C# and Visual Basic).

    // Covariant interface.

    interface ICovariant<out R> { }

    // Extending covariant interface.

    interface IExtCovariant<out R> : ICovariant<R> { }

    // Implementing covariant interface.

    class Sample<R> : ICovariant<R> { }

    ICovariant<Object> iobj = new Sample<Object>();

    ICovariant<String> istr = new Sample<String>();

    // You can assign istr to iobj because

    // the ICovariant interface is covariant.

    iobj = istr;

    out (generic modifier) See above
    override The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event.An override method provides a new implementation of a member that is inherited from a base class. The method that is overridden by an override declaration is known as the overridden base method. The overridden base method must have the same signature as the override method. For information about inheritance, see Inheritance (C# Programming Guide).You cannot override a non-virtual or static method. The overridden base method must be virtual, abstract, or override.An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.You cannot use the new, static, or virtual modifiers to modify an override method.An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property, and the overridden property must be virtual, abstract, or override.

    For more information about how to use the override keyword, see Versioning with the Override and New Keywords (C# Programming Guide) and Knowing when to use Override and New Keywords.

    params The params keyword lets you specify a method parameter that takes a variable number of arguments.You can send a comma-separated list of arguments of the type specified in the parameter declaration, or an array of arguments of the specified type. You also can send no arguments.No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration.
    private The private keyword is a member access modifier. Private access is the least permissive access level. Private members are accessible only within the body of the class or the struct in which they are declared.Nested types in the same body can also access those private members.It is a compile-time error to reference a private member outside the class or the struct in which it is declared.
    protected The protected keyword is a member access modifier. A protected member is accessible within its class and by derived class instances. For a comparison of protected with the other access modifiers, see Accessibility Levels.
    public The public keyword is an access modifier for types and type members. Public access is the most permissive access level. There are no restrictions on accessing public members.
    readonly The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
    ref The ref keyword causes arguments to be passed by reference. The effect is that any changes to the parameter in the method will be reflected in that variable when control passes back to the calling method.Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not related; a method parameter can be modified by ref regardless of whether it is a value type or a reference type. Therefore, there is no boxing of a value type when it is passed by reference.To use a ref parameter, both the method definition and the calling method must explicitly use the ref keyword.
    return The return statement terminates execution of the method in which it appears and returns control to the calling method. It can also return an optional value. If the method is a void type, the return statement can be omitted.If the return statement is inside a try block, the finally block, if one exists, will be executed before control returns to the calling method.
    sbyte The sbyte keyword indicates an integral type that stores values according to the size (Signed 8-bit integer) and range (-128 to 127)
    sealed When applied to a class, the sealed modifier prevents other classes from inheriting from it. In the following example, class B inherits from class A, but no class can inherit from class B.You can also use the sealed modifier on a method or property that overrides a virtual method or property in a base class. This enables you to allow classes to derive from your class and prevent them from overriding specific virtual methods or properties.
    short The short keyword denotes an integral data type that stores values according to the size(Signed 16-bit integer) and range (-32,768 to 32,767)
    sizeof Used to obtain the size in bytes for an unmanaged type. Unmanaged types include the built-in types that are listed in the table that follows, and also the following:

    • Enum types
    • Pointer types
    • User-defined structs that do not contain any fields or properties that are reference types
    stackalloc The stackalloc keyword is used in an unsafe code context to allocate a block of memory on the stack.int* block = stackalloc int[100];
    static Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used with classes, fields, methods, properties, operators, events, and constructors, but it cannot be used with indexers, destructors, or types other than classes. For more information, see Static Classes and Static Class Members (C# Programming Guide).A constant or type declaration is implicitly a static member.A static member cannot be referenced through an instance. Instead, it is referenced through the type name.While an instance of a class contains a separate copy of all instance fields of the class, there is only one copy of each static field.It is not possible to use this to reference static methods or property accessors.If the static keyword is applied to a class, all the members of the class must be static.

    Classes and static classes may have static constructors. Static constructors are called at some point between when the program starts and the class is instantiated.

    string The string type represents a sequence of zero or more Unicode characters. string is an alias for String in the .NET Framework.Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references. This makes testing for string equality more intuitive.Strings are immutable–the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this.
    struct A struct type is a value type that is typically used to encapsulate small groups of related variables, such as the coordinates of a rectangle or the characteristics of an item in an inventory.Structs can also contain constructors, constants, fields, methods, properties, indexers, operators, events, and nested types, although if several such members are required, you should consider making your type a class instead.Structs can implement an interface but they cannot inherit from another struct. For that reason, struct members cannot be declared as protected.
    switch The switch statement is a control statement that selects a switch section to execute from a list of candidates.Each switch section contains one or more case labels and a list of one or more statements. The following example shows a simple switch statement that has three switch sections. Each switch section has one case label, such as case 1, and a list of two statements.
    this The this keyword refers to the current instance of the class and is also used as a modifier of the first parameter of an extension method.see Extension Methods (C# Programming Guide).: Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.namespace ExtensionMethods{public static class MyExtensions{

    public static int WordCount(this String str)

    {

    return str.Split(new char[] { ‘ ‘, ‘.’, ‘?’ }, StringSplitOptions.RemoveEmptyEntries).Length;

    }

    }

    }

    The following example shows an extension method defined for the System.String class.

    throw The throw statement is used to signal the occurrence of an anomalous situation (exception) during the program execution.Usually the throw statement is used with try-catch or try-finally statements.
    true Used as an overloaded operator or as a literal:true Operator : Returns the bool value true to indicate that an operand is true and returns false otherwise. The language now provides built-in support for nullable value types, and whenever possible you should use those instead of overloading the true and false operators. For more information, see Nullable Types (C# Programming Guide).true Literal : Represents the boolean value true.
    try The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions. When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. If the currently executing method does not contain such a catch block, the CLR looks at the method that called the current method, and so on up the call stack. If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.
    typeof Used to obtain the System.Type object for a type. A typeof expression takes the following form:System.Type type = typeof(int);
    uint The uint keyword signifies an integral type that stores values according to the size (Unsigned 32-bit integer) and range (0 to 4,294,967,295)
    ulong The ulong keyword signifies an integral type that stores values according to the size (Unsigned 64-bit integer) and range (0 to 18,446,744,073,709,551,615)
    unchecked The unchecked keyword is used to suppress overflow-checking for integral-type arithmetic operations and conversions.In an unchecked context, if an expression produces a value that is outside the range of the destination type, the overflow is not flagged. For example, because the calculation in the following example is performed in an unchecked block or expression, the fact that the result is too large for an integer is ignored, and int1 is assigned the value -2,147,483,639.unchecked{int1 = 2147483647 + 10;}

    int1 = unchecked(ConstantMax + 10);

    unsafe The unsafe keyword denotes an unsafe context, which is required for any operation involving pointers. For more information, see Unsafe Code and Pointers (C# Programming Guide).You can use the unsafe modifier in the declaration of a type or a member. The entire textual extent of the type or member is therefore considered an unsafe context. For example, the following is a method declared with the unsafe modifier:To compile unsafe code, you must specify the /unsafe compiler option. Unsafe code is not verifiable by the common language runtime.
    ushort The ushort keyword indicates an integral data type that stores values according to the size(Unsigned 16-bit integer) and range (0 to 65,535)
    using The using keyword has two major uses:

    • As a directive, when it is used to create an alias for a namespace or to import types defined in other namespaces. See using Directive.

    As a statement, when it defines a scope at the end of which an object will be disposed. See using Statement : Provides a convenient syntax that ensures the correct use of IDisposable objects. File and Font are examples of managed types that access unmanaged resources (in this case file handles and device contexts). There are many other kinds of unmanaged resources and class library types that encapsulate them. All such types must implement the IDisposable interface.

    As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

    The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

    virtual The virtual keyword is used to modify a method, property, indexer, or event declaration and allow for it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it:public virtual double Area(){return x * y;}The implementation of a virtual member can be changed by an overriding member in a derived class. For more information about how to use the virtual keyword, see Versioning with the Override and New Keywords (C# Programming Guide) and Knowing When to Use Override and New Keywords (C# Programming Guide).

    When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.

    By default, methods are non-virtual. You cannot override a non-virtual method.

    You cannot use the virtual modifier with the static, abstract, private, or override modifiers.

    Virtual properties behave like abstract methods, except for the differences in declaration and invocation syntax.

    • It is an error to use the virtual modifier on a static property.
    • A virtual inherited property can be overridden in a derived class by including a property declaration that uses the override modifier.
    void When used as the return type for a method, void specifies that the method does not return a value.void is not allowed in the parameter list of a method.void is also used in an unsafe context to declare a pointer to an unknown type. For more information, see Pointer types (C# Programming Guide).void is an alias for the .NET Framework System.Void type.
    volatile The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.The volatile keyword can be applied to fields of these types:

    • Reference types.
    • Pointer types (in an unsafe context). Note that although the pointer itself can be volatile, the object that it points to cannot. In other words, you cannot declare a “pointer to volatile.”
    • Types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
    • An enum type with one of the following base types: byte, sbyte, short, ushort, int, or uint.
    • Generic type parameters known to be reference types.
    • IntPtr and UIntPtr.

    The volatile keyword can only be applied to fields of a class or struct. Local variables cannot be declared volatile.

    The following example demonstrates how an auxiliary or worker thread can be created and used to perform processing in parallel with that of the primary thread. For background information about multithreading, see Managed Threading and Threading (C# and Visual Basic).

    using System;

    using System.Threading;

    public class Worker

    {

    // This method is called when the thread is started.

    public void DoWork()

    {

    while (!_shouldStop)

    {

    Console.WriteLine(“Worker thread: working…”);

    }

    Console.WriteLine(“Worker thread: terminating gracefully.”);

    }

    public void RequestStop()

    {

    _shouldStop = true;

    }

    // Keyword volatile is used as a hint to the compiler that this data

    // member is accessed by multiple threads.

    private volatile bool _shouldStop;

    }

    public class WorkerThreadExample

    {

    static void Main()

    {

    // Create the worker thread object. This does not start the thread.

    Worker workerObject = new Worker();

    Thread workerThread = new Thread(workerObject.DoWork);

    // Start the worker thread.

    workerThread.Start();

    Console.WriteLine(“Main thread: starting worker thread…”);

    // Loop until the worker thread activates.

    while (!workerThread.IsAlive) ;

    // Put the main thread to sleep for 1 millisecond to

    // allow the worker thread to do some work.

    Thread.Sleep(1);

    // Request that the worker thread stop itself.

    workerObject.RequestStop();

    // Use the Thread.Join method to block the current thread

    // until the object’s thread terminates.

    workerThread.Join();

    Console.WriteLine(“Main thread: worker thread has terminated.”);

    }

    // Sample output:

    // Main thread: starting worker thread…

    // Worker thread: working…

    // Worker thread: working…

    // Worker thread: working…

    // Worker thread: working…

    // Worker thread: working…

    // Worker thread: working…

    // Worker thread: terminating gracefully.

    // Main thread: worker thread has terminated.

    }

    while The while statement executes a statement or a block of statements until a specified expression evaluates to false.

    Contextual Keywords


    A contextual keyword is used to provide a specific meaning in the code, but it is not a reserved word in C#. Some contextual keywords, such as partial and where, have special meanings in two or more contexts.

    Keywords Description
    add The add contextual keyword is used to define a custom event accessor that is invoked when client code subscribes to your event. If you supply a custom add accessor, you must also supply a remove accessor.class Events : IDrawingObject{event EventHandler PreDrawEvent;event EventHandler IDrawingObject.OnDraw{

    add

    {

    lock (PreDrawEvent)

    {

    PreDrawEvent += value;

    }

    }

    remove

    {

    lock (PreDrawEvent)

    {

    PreDrawEvent -= value;

    }

    }

    }

    }

    You do not typically need to provide your own custom event accessors. The accessors that are automatically generated by the compiler when you declare an event are sufficient for most scenarios.

    alias You might have to reference two versions of assemblies that have the same fully-qualified type names. For example, you might have to use two or more versions of an assembly in the same application. By using an external assembly alias, the namespaces from each assembly can be wrapped inside root-level namespaces named by the alias, which enables them to be used in the same file.To reference two assemblies with the same fully-qualified type names, an alias must be specified at a command prompt, as follows:/r:GridV1=grid.dll/r:GridV2=grid20.dllThis creates the external aliases GridV1 and GridV2. To use these aliases from within a program, reference them by using the extern keyword. For example:extern alias GridV1;

    extern alias GridV2;

    Each extern alias declaration introduces an additional root-level namespace that parallels (but does not lie within) the global namespace. Thus types from each assembly can be referred to without ambiguity by using their fully qualified name, rooted in the appropriate namespace-alias.

    ascending The ascending contextual keyword is used in the orderby clause in query expressions to specify that the sort order is from smallest to largest. Because ascending is the default sort order, you do not have to specify it.IEnumerable<string> sortAscendingQuery =from vegetable in vegetablesorderby vegetable ascendingselect vegetable;See : LINQ Query Expressions (C# Programming Guide)
    descending The descending contextual keyword is used in the orderby clause in query expressions to specify that the sort order is from largest to smallest.
    dynamic The dynamic type enables the operations in which it occurs to bypass compile-time type checking. Instead, these operations are resolved at run time. The type simplifies access to COM APIs such as the Office Automation APIs, and also to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).Type dynamic behaves like type object in most circumstances. However, operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at run time.class Program{static void Main(string[] args){

    dynamic dyn = 1;

    object obj = 1;

    // Rest the mouse pointer over dyn and obj to see their

    // types at compile time.

    System.Console.WriteLine(dyn.GetType());

    System.Console.WriteLine(obj.GetType());

    }

    }

    The following example contrasts a variable of type dynamic to a variable of type object. To verify the type of each variable at compile time, place the mouse pointer over dyn or obj in the WriteLine statements. IntelliSense shows dynamic for dyn and object for obj.

    from A query expression must begin with a from clause. Additionally, a query expression can contain sub-queries, which also begin with a from clause. The from clause specifies the following:

    • The data source on which the query or sub-query will be run.
    • A local range variable that represents each element in the source sequence.

    Both the range variable and the data source are strongly typed. The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>.

    get The get keyword defines an accessor method in a property or indexer that retrieves the value of the property or the indexer element. For more information, see Properties (C# Programming Guide), Auto-Implemented Properties (C# Programming Guide) and Indexers (C# Programming Guide).
    global The global contextual keyword, when it comes before the :: operator, refers to the global namespace, which is the default namespace for any C# program and is otherwise unnamed. For more information, see How to: Use the Namespace Alias Qualifier (C# Programming Guide).class TestClass : global::TestApp { }
    group The group clause returns a sequence of IGrouping<TKey, TElement> objects that contain zero or more items that match the key value for the group. For example, you can group a sequence of strings according to the first letter in each string. In this case, the first letter is the key and has a type char, and is stored in the Key property of each IGrouping<TKey, TElement> object. The compiler infers the type of the key.You can end a query expression with a group clause, as shown in the following example:// Query variable is an IEnumerable<IGrouping<char, Student>>var studentQuery1 =from student in studentsgroup student by student.Last[0];

    If you want to perform additional query operations on each group, you can specify a temporary identifier by using the into contextual keyword. When you use into, you must continue with the query, and eventually end it with either a select statement or another group clause, as shown in the following excerpt:

    // Group students by the first letter of their last name

    // Query variable is an IEnumerable<IGrouping<char, Student>>

    var studentQuery2 =

    from student in students

    group student by student.Last[0] into g

    orderby g.Key

    select g;

    into The into contextual keyword can be used to create a temporary identifier to store the results of a group, join or select clause into a new identifier. This identifier can itself be a generator for additional query commands. When used in a group or select clause, the use of the new identifier is sometimes referred to as a continuation.
    join The join clause is useful for associating elements from different source sequences that have no direct relationship in the object model. The only requirement is that the elements in each source share some value that can be compared for equality. For example, a food distributor might have a list of suppliers of a certain product, and a list of buyers. A join clause can be used, for example, to create a list of the suppliers and buyers of that product who are all in the same specified region.A join clause takes two source sequences as input. The elements in each sequence must either be or contain a property that can be compared to a corresponding property in the other sequence. The join clause compares the specified keys for equality by using the special equals keyword. All joins performed by the join clause are equijoins. The shape of the output of a join clause depends on the specific type of join you are performing. The following are three most common join types:

    • Inner join
    • Group join : A group join produces a hierarchical result sequence, which associates elements in the left source sequence with one or more matching elements in the right side source sequence. A group join has no equivalent in relational terms; it is essentially a sequence of object arrays.
    • Left outer join

    var innerJoinQuery =

    from category in categories

    join prod in products on category.ID equals prod.CategoryID

    select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence

    let In a query expression, it is sometimes useful to store the result of a sub-expression in order to use it in subsequent clauses. You can do this with the let keyword, which creates a new range variable and initializes it with the result of the expression you supply. Once initialized with a value, the range variable cannot be used to store another value. However, if the range variable holds a queryable type, it can be queried.string[] strings ={“A penny saved is a penny earned.”,”The early bird catches the worm.”,”The pen is mightier than the sword.”

    };

    // Split the sentence into an array of words

    // and select those whose first letter is a vowel.

    var earlyBirdQuery =

    from sentence in strings

    let words = sentence.Split(‘ ‘)

    from word in words

    let w = word.ToLower()

    where w[0] == ‘a’ || w[0] == ‘e’

    || w[0] == ‘i’ || w[0] == ‘o’

    || w[0] == ‘u’

    select word;

    orderby In a query expression, the orderby clause causes the returned sequence or subsequence (group) to be sorted in either ascending or descending order. Multiple keys can be specified in order to perform one or more secondary sort operations. The sorting is performed by the default comparer for the type of the element. The default sort order is ascending. You can also specify a custom comparer. However, it is only available by using method-based syntax. For more information, see Sorting Data.
    partial (type) Partial type definitions allow for the definition of a class, struct, or interface to be split into multiple files. Splitting a class, struct or interface type over several files can be useful when you are working with large projects, or with automatically generated code such as that provided by the Windows Forms Designer. A partial type may contain a partial method. For more information, see Partial Classes and Methods (C# Programming Guide).
    partial (method) A partial method has its signature defined in one part of a partial type, and its implementation defined in another part of the type. Partial methods enable class designers to provide method hooks, similar to event handlers, that developers may decide to implement or not. If the developer does not supply an implementation, the compiler removes the signature at compile time. The following conditions apply to partial methods:

    • Signatures in both parts of the partial type must match.
    • The method must return void.
    • No access modifiers or attributes are allowed. Partial methods are implicitly private.
    remove The remove contextual keyword is used to define a custom event accessor that is invoked when client code unsubscribes from your event. If you supply a custom remove accessor, you must also supply an add accessor.
    select In a query expression, the select clause specifies the type of values that will be produced when the query is executed. The result is based on the evaluation of all the previous clauses and on any expressions in the select clause itself. A query expression must terminate with either a select clause or a group clause.//Create the data sourceList<int> Scores = new List<int>() { 97, 92, 81, 60 };// Create the query.IEnumerable<int> queryHighScores =from score in Scores

    where score > 80

    select score;

    set The set keyword defines an accessor method in a property or indexer that assigns the value of the property or the indexer element. For more information, see Properties (C# Programming Guide), Auto-Implemented Properties (C# Programming Guide), and Indexers (C# Programming Guide).
    value The contextual keyword value is used in the set accessor in ordinary property declarations. It is similar to an input parameter on a method. The word value references the value that client code is attempting to assign to the property. In the following example, MyDerivedClass has a property called Name that uses the value parameter to assign a new string to the backing field name. From the point of view of client code, the operation is written as a simple assignment.class MyBaseClass{// virtual auto-implemented property. Overrides can only// provide specialized behavior if they implement get and set accessors.public virtual string Name { get; set; }

    // ordinary virtual property with backing field

    private int num;

    public virtual int Number

    {

    get { return num; }

    set { num = value; }

    }

    }

    class MyDerivedClass : MyBaseClass

    {

    private string name;

    // Override auto-implemented property with ordinary property

    // to provide specialized accessor behavior.

    public override string Name

    {

    get

    {

    return name;

    }

    set

    {

    if (value != String.Empty)

    {

    name = value;

    }

    else

    {

    name = “Unknown”;

    }

    }

    }

    }

    var Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. The following two declarations of i are functionally equivalent:var i = 10; // implicitly typedint i = 10; //explicitly typed
    where (generic type constraint) In a generic type definition, the where clause is used to specify constraints on the types that can be used as arguments for a type parameter defined in a generic declaration. For example, you can declare a generic class, MyGenericClass, such that the type parameter T implements the IComparable<T> interface:For more information on the where clause in a query expression, see where clause (C# Reference).
    where (query clause) The where clause is used in a query expression to specify which elements from the data source will be returned in the query expression. It applies a Boolean condition (predicate) to each source element (referenced by the range variable) and returns those for which the specified condition is true. A single query expression may contain multiple where clauses and a single clause may contain multiple predicate subexpressions.
    yield The yield keyword signals to the compiler that the method in which it appears is an iterator block. The compiler generates a class to implement the behavior that is expressed in the iterator block. In the iterator block, the yield keyword is used together with the return keyword to provide a value to the enumerator object. This is the value that is returned, for example, in each loop of a foreach statement. The yield keyword is also used with break to signal the end of iteration. For more information about iterators, see Iterators (C# Programming Guide). The following example shows the two forms of the yield statement.yield return <expression>;yield break;In a yield return statement, expression is evaluated and returned as a value to the enumerator object; expression has to be implicitly convertible to the yield type of the iterator.In a yield break statement, control is unconditionally returned to the caller of the iterator, which is either the IEnumerator.MoveNext method (or its generic System.Collections.Generic.IEnumerable<T> counterpart) or the Dispose method of the enumerator object.The yield statement can only appear inside an iterator block, which can be implemented as the body of a method, operator, or accessor. The body of such methods, operators, or accessors is controlled by the following restrictions:

    • Unsafe blocks are not allowed.
    • Parameters to the method, operator, or accessor cannot be ref or out.
    • A yield return statement cannot be located anywhere inside a try-catch block. It can be located in a try block if the try block is followed by a finally block.
    • A yield break statement may be located in a try block or a catch block but not a finally block.

    A yield statement cannot appear in an anonymous method. For more information, see Anonymous Methods (C# Programming Guide).

    When used with expression, a yield return statement cannot appear in a catch block or in a try block that has one or more catch clauses. For more information, see Exception Handling Statements (C# Reference).

    public class List

    {

    //using System.Collections;

    public static IEnumerable Power(int number, int exponent)

    {

    int counter = 0;

    int result = 1;

    while (counter++ < exponent)

    {

    result = result * number;

    yield return result;

    }

    }

    static void Main()

    {

    // Display powers of 2 up to the exponent 8:

    foreach (int i in Power(2, 8))

    {

    Console.Write(“{0} “, i);

    }

    }

    }

    /*

    Output:

    2 4 8 16 32 64 128 256

    */

    You may be interested in The C# Language on msdn which will cover C# Operators , C# Preprocessor Directives, C# Language Features and C# Language Tutorials.

    The above article contents are from MSDN links mentioned above and whole credit goes to msdn team for proving such an extensive information. The purpose of this article is to quickly review the c# concepts and fill in the gaps in articles that appears under .Net Concepts on this blog.

  • .Net Garbage collection (GC)

     In this article we are going to cover Garbage collection algorithm, Finalization (internals), Resurrection, Weak Reference (Short and long – internals), Generations, GC methods and GC 4.0 features (Background GC).

    Garbage collection in the Microsoft .NET common language runtime environment completely absolves the developer from tracking memory usage and knowing when to free memory. This article gives a detailed step-by-step description of how the garbage collection algorithm works internally.
    Every program uses resources of one sort or another “memory buffers, screen space, network connections, database resources, and so on.
    The steps required to access a resource are as follows:

    • Allocate memory for the type that represents the resource.
    • Initialize the memory to set the initial state of the resource and to make the resource usable.
    • Use the resource by accessing the instance members of the type (repeat as necessary).
    • Tear down the state of the resource to clean up.
    • Free the memory.

    This seemingly simple paradigm has been one of the major sources of programming errors.
    As I examine GC, you’ll notice that it completely absolves the developer from tracking memory usage and knowing when to free memory. However, the garbage collector doesn’t know anything about the resource represented by the type in memory. This means that a garbage collector can’t know how to perform step four “tearing down the state of a resource. To get a resource to clean up properly, the developer must write code that knows how to properly clean up a resource. In the .NET Framework, the developer writes this code in a Close, Dispose, or Finalize method, which I’ll describe later. However, as you’ll see later, the garbage collector can determine when to call this method automatically.
    Also, many types represent resources that do not require any cleanup. For example, a Rectangle resource can be completely cleaned up simply by destroying the left, right, width, and height fields maintained in the type’s memory. On the other hand, a type that represents a file resource or a network connection resource will require the execution of some explicit clean up code when the resource is to be destroyed.
     

    Resource Allocation

     
    The Microsoft® .NET common language runtime requires that all resources be allocated from the managed heap. There are several GC algorithms in use today. Each algorithm is fine-tuned for a particular environment in order to provide the best performance. This article concentrates on the GC algorithm that is used by the common language runtime.

    When a process is initialized, the runtime reserves a contiguous region of address space that initially has no storage allocated for it. This address space region is the managed heap. The heap also maintains a pointer, which I’ll call the NextObjPtr. This pointer indicates where the next object is to be allocated within the heap. Initially, the NextObjPtr is set to the base address of the reserved address space region.
    An application creates an object using the new operator. This operator first makes sure that the bytes required by the new object fit in the reserved region (committing storage if necessary). If the object fits, then NextObjPtr points to the object in the heap, this object’s constructor is called, and the new operator returns the address of the object.

     

     

     

    Figure 1 Managed Heap

     

    At this point, NextObjPtr is incremented past the object so that it points to where the next object will be placed in the heap. Figure 1 shows a managed heap consisting of three objects: A, B, and C. The next object to be allocated will be placed where NextObjPtr points (immediately after object C).
    For the managed heap, allocating an object simply means adding a value to a pointer. Here we are assuming that address space and storage are infinite.
    When an application calls the new operator to create an object, there may not be enough address space left in the region to allocate to the object. The heap detects this by adding the size of the new object to NextObjPtr. If NextObjPtr is beyond the end of the address space region, then the heap is full and a collection must be performed.
    In reality, a collection occurs when generation 0 is completely full. Briefly, a generation is a mechanism implemented by the garbage collector in order to improve performance. The idea is that newly created objects are part of a young generation, and objects created early in the application’s lifecycle are in an old generation. Separating objects into generations can allow the garbage collector to collect specific generations instead of collecting all objects in the managed heap. We will discuss the generation in detail further in this article.

     

    The Garbage Collection Algorithm

     
    The garbage collector checks to see if there are any objects in the heap that are no longer being used by the application. If such objects exist, then the memory used by these objects can be reclaimed. (If no more memory is available for the heap, then the new operator throws an OutOfMemoryException.)
    Every application has a set of roots. Roots identify storage locations, which refer to objects on the managed heap or to objects that are set to null. For example, all the global and static object pointers in an application are considered part of the application’s roots. In addition, any local variable/parameter object pointers on a thread’s stack are considered part of the application’s roots. Finally, any CPU registers containing pointers to objects in the managed heap are also considered part of the application’s roots. The list of active roots is maintained by the just-in-time (JIT) compiler and common language runtime, and is made accessible to the garbage collector’s algorithm.
    When the garbage collector starts running, it makes the assumption that all objects in the heap are garbage. In other words, it assumes that none of the application’s roots refer to any objects in the heap. Now, the garbage collector starts walking the roots and building a graph of all objects reachable from the roots. For example, the garbage collector may locate a global variable that points to an object in the heap.
    Figure 2 shows a heap with several allocated objects where the application’s roots refer directly to objects A, C, D, and F. All of these objects become part of the graph. When adding object D, the collector notices that this object refers to object H, and object H is also added to the graph. The collector continues to walk through all reachable objects recursively.

     

     

     

     

     

     

     

     

     

     

    Figure 2 Allocated Objects in Heap

     

    Once this part of the graph is complete, the garbage collector checks the next root and walks the objects again. As the garbage collector walks from object to object, if it attempts to add an object to the graph that it previously added, then the garbage collector can stop walking down that path. This serves two purposes. First, it helps performance significantly since it doesn’t walk through a set of objects more than once. Second, it prevents infinite loops should you have any circular linked lists of objects.
    Once all the roots have been checked, the garbage collector’s graph contains the set of all objects that are somehow reachable from the application’s roots; any objects that are not in the graph are not accessible by the application, and are therefore considered garbage. The garbage collector now walks through the heap linearly, looking for contiguous blocks of garbage objects (now considered free space). The garbage collector then shifts the non-garbage objects down in memory (using the standard memcpy function that you’ve known for years), removing all of the gaps in the heap. Of course, moving the objects in memory invalidates all pointers to the objects. So the garbage collector must modify the application’s roots so that the pointers point to the objects’ new locations. In addition, if any object contains a pointer to another object, the garbage collector is responsible for correcting these pointers as well. Figure 3 shows the managed heap after a collection.


     

    Figure 3 Managed Heap after Collection

     

    After all the garbage has been identified, all the non-garbage has been compacted, and all the non-garbage pointers have been fixed-up, the NextObjPtr is positioned just after the last non-garbage object. At this point, the new operation is tried again and the resource requested by the application is successfully created.
    It is not possible to leak resources, since any resource not accessible from your application’s roots can be collected at some point. Second, it is not possible to access a resource that is freed, since the resource won’t be freed if it is reachable. If it’s not reachable, then your application has no way to access it.

    Finalization

     
    The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource’s memory.
    when the garbage collector detects that an object is garbage, the garbage collector calls the object’s Finalize method (if it exists) and then the object’s memory is reclaimed. For example, let’s say you have the following type (in C#):
    public class BaseObj {
    public BaseObj() {
    }

    protected override void Finalize() {
    // Perform resource cleanup code here…
    // Example: Close file/Close network connection
    Console.WriteLine(“In Finalize.”);
    }
    }
    Now you can create an instance of this object by calling:
    BaseObj bo = new BaseObj();

    Some time in the future, the garbage collector will determine that this object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing “In Finalize” to appear in the console window and reclaiming the memory block used by this object.
    When designing a type it is best to avoid using a Finalize method. There are several reasons for this:

    • Finalizable objects get promoted to older generations, which increases memory pressure and prevents the object’s memory from being collected when the garbage collector determines the object is garbage. In addition, all objects referred to directly or indirectly by this object get promoted as well. Generations and promotions will be discussed in this article below.
    • Finalizable objects take longer to allocate.
    • Forcing the garbage collector to execute a Finalize method can significantly hurt performance. Remember, each object is finalized. So if I have an array of 10,000 objects, each object must have its Finalize method called.
    • Finalizable objects may refer to other (non-finalizable) objects, prolonging their lifetime unnecessarily. In fact, you might want to consider breaking a type into two different types: a lightweight type with a Finalize method that doesn’t refer to any other objects, and a separate type without a Finalize method that does refer to other objects.
    • You have no control over when the Finalize method will execute. The object may hold on to resources until the next time the garbage collector runs.
    • When an application terminates, some objects are still reachable and will not have their Finalize method called. This can happen if background threads are using the objects or if objects are created during application shutdown or AppDomain unloading. In addition, by default, Finalize methods are not called for unreachable objects when an application exits so that the application may terminate quickly. Of course, all operating system resources will be reclaimed, but any objects in the managed heap are not able to clean up gracefully. You can change this default behavior by calling the System.GC type’s RequestFinalizeOnShutdown method. However, you should use this method with care since calling it means that your type is controlling a policy for the entire application.
    • The runtime doesn’t make any guarantees as to the order in which Finalize methods are called. For example, let’s say there is an object that contains a pointer to an inner object. The garbage collector has detected that both objects are garbage. Furthermore, say that the inner object’s Finalize method gets called first. Now, the outer object’s Finalize method is allowed to access the inner object and call methods on it, but the inner object has been finalized and the results may be unpredictable. For this reason, it is strongly recommended that Finalize methods not access any inner, member objects.

     

    If you determine that your type must implement a Finalize method, then make sure the code executes as quickly as possible. Avoid all actions that would block the Finalize method, including any thread synchronization operations. Also, if you let any exceptions escape the Finalize method, the system just assumes that the Finalize method returned and continues calling other objects’ Finalize methods.

    Finalization Internals

     
    When an application creates a new object, the new operator allocates the memory from the heap. If the object’s type contains a Finalize method, then a pointer to the object is placed on the finalization queue. The finalization queue is an internal data structure controlled by the garbage collector. Each entry in the queue points to an object that should have its Finalize method called before the object’s memory can be reclaimed.
    Figure 5 shows a heap containing several objects. Some of these objects are reachable from the application’s roots, and some are not. When objects C, E, F, I, and J were created, the system detected that these objects had Finalize methods and pointers to these objects were added to the finalization queue.

     

    Figure 5 A Heap with Many Objects

     

    When a GC occurs, objects B, E, G, H, I, and J are determined to be garbage. The garbage collector scans the finalization queue looking for pointers to these objects. When a pointer is found, the pointer is removed from the finalization queue and appended to the freachable queue (pronounced “F-reachable”). The freachable queue is another internal data structure controlled by the garbage collector. Each pointer in the freachable queue identifies an object that is ready to have its Finalize method called.
    After the collection, the managed heap looks like Figure 6. Here, you see that the memory occupied by objects B, G, and H has been reclaimed because these objects did not have a Finalize method that needed to be called. However, the memory occupied by objects E, I, and J could not be reclaimed because their Finalize method has not been called yet.

    Figure 6 Managed Heap after Garbage Collection

     

    There is a special runtime thread dedicated to calling Finalize methods. When the freachable queue is empty (which is usually the case), this thread sleeps. But when entries appear, this thread wakes, removes each entry from the queue, and calls each object’s Finalize method. Because of this, you should not execute any code in a Finalize method that makes any assumption about the thread that’s executing the code. For example, avoid accessing thread local storage in the Finalize method.
    The interaction of the finalization queue and the freachable queue is quite fascinating. First, let me tell you how the freachable queue got its name. The f is obvious and stands for finalization; every entry in the freachable queue should have its Finalize method called. The “reachable” part of the name means that the objects are reachable. To put it another way, the freachable queue is considered to be a root just like global and static variables are roots. Therefore, if an object is on the freachable queue, then the object is reachable and is not garbage.

    In short, when an object is not reachable, the garbage collector considers the object garbage. Then, when the garbage collector moves an object’s entry from the finalization queue to the freachable queue, the object is no longer considered garbage and its memory is not reclaimed. At this point, the garbage collector has finished identifying garbage. Some of the objects identified as garbage have been reclassified as not garbage. The garbage collector compacts the reclaimable memory and the special runtime thread empties the freachable queue, executing each object’s Finalize method.

     

    Figure 7 Managed Heap after Second Garbage Collection

    The next time the garbage collector is invoked, it sees that the finalized objects are truly garbage, since the application’s roots don’t point to it and the freachable queue no longer points to it. Now the memory for the object is simply reclaimed. The important thing to understand here is that two GCs are required to reclaim memory used by objects that require finalization. In reality, more than two collections may be necessary since the objects could get promoted to an older generation. Figure 7 shows what the managed heap looks like after the second GC.

    Resurrection

     
    The whole concept of finalization is fascinating. However, there is more to it than what I’ve described so far. You’ll notice in the previous section that when an application is no longer accessing a live object, the garbage collector considers the object to be dead. However, if the object requires finalization, the object is considered live again until it is actually finalized, and then it is permanently dead. In other words, an object requiring finalization dies, lives, and then dies again. This is a very interesting phenomenon called resurrection. Resurrection, as its name implies, allows an object to come back from the dead.

    I’ve already described a form of resurrection. When the garbage collector places a reference to the object on the freachable queue, the object is reachable from a root and has come back to life. Eventually, the object’s Finalize method is called, no roots point to the object, and the object is dead forever after. But what if an object’s Finalize method executed code that placed a pointer to the object in a global or static variable?
    public class BaseObj {
    protected override void Finalize() {
    Application.ObjHolder = this;
    }
    }

    class Application {
    static public Object ObjHolder;    // Defaults to null
    }
    In this case, when the object’s Finalize method executes, a pointer to the object is placed in a root and the object is reachable from the application’s code. This object is now resurrected and the garbage collector will not consider the object to be garbage. The application is free to use the object, but it is very important to note that the object has been finalized and that using the object may cause unpredictable results. Also note: if BaseObj contained members that pointed to other objects (either directly or indirectly), all objects would be resurrected, since they are all reachable from the application’s roots. However, be aware that some of these other objects may also have been finalized.

    In fact, when designing your own object types, objects of your type can get finalized and resurrected totally out of your control. Implement your code so that you handle this gracefully. For many types, this means keeping a Boolean flag indicating whether the object has been finalized or not. Then, if methods are called on your finalized object, you might consider throwing an exception. The exact technique to use depends on your type.

    Now, if some other piece of code sets Application.ObjHolder to null, the object is unreachable. Eventually the garbage collector will consider the object to be garbage and will reclaim the object’s storage. Note that the object’s Finalize method will not be called because no pointer to the object exists on the finalization queue.
    There are very few good uses of resurrection, and you really should avoid it if possible. However, when people do use resurrection, they usually want the object to clean itself up gracefully every time the object dies. To make this possible, the GC type offers a method called ReRegisterForFinalize, which takes a single parameter: the pointer to an object.
    public class BaseObj {
    protected override void Finalize() {
    Application.ObjHolder = this;
    GC.ReRegisterForFinalize(this);
    }
    }
    When this object’s Finalize method is called, it resurrects itself by making a root point to the object. The Finalize method then calls ReRegisterForFinalize, which appends the address of the specified object (this) to the end of the finalization queue. When the garbage collector detects that this object is unreachable again, it will queue the object’s pointer on the freachable queue and the Finalize method will get called again. This specific example shows how to create an object that constantly resurrects itself and never dies, which is usually not desirable. It is far more common to conditionally set a root to reference the object inside the Finalize method.

    Forcing an Object to Clean Up

     

    If you can, you should try to define objects that do not require any clean up. Unfortunately, for many objects, this is simply not possible. So for these objects, you must implement a Finalize method as part of the type’s definition. However, it is also recommended that you add an additional method to the type that allows a user of the type to explicitly clean up the object when they want. By convention, this method should be called Close or Dispose.
    In general, you use Close if the object can be reopened or reused after it has been closed. You also use Close if the object is generally considered to be closed, such as a file. On the other hand, you would use Dispose if the object should no longer be used at all after it has been disposed. For example, to delete a System.Drawing.Brush object, you call its Dispose method. Once disposed, the Brush object cannot be used, and calling methods to manipulate the object may cause exceptions to be thrown. If you need to work with another Brush, you must construct a new Brush object.

    Now, let’s look at what the Close/Dispose method is supposed to do. The System.IO.FileStream type allows the user to open a file for reading and writing. To improve performance, the type’s implementation makes use of a memory buffer. Only when the buffer fills does the type flush the contents of the buffer to the file. Let’s say that you create a new FileStream object and write just a few bytes of information to it. If these bytes don’t fill the buffer, then the buffer is not written to disk. The FileStream type does implement a Finalize method, and when the FileStream object is collected the Finalize method flushes any remaining data from memory to disk and then closes the file.

    But this approach may not be good enough for the user of the FileStream type. Let’s say that the first FileStream object has not been collected yet, but the application wants to create a new FileStream object using the same disk file. In this scenario, the second FileStream object will fail to open the file if the first FileStream object had the file open for exclusive access. The user of the FileStream object must have some way to force the final memory flush to disk and to close the file.

    If you examine the FileStream type’s documentation, you’ll see that it has a method called Close. When called, this method flushes the remaining data in memory to the disk and closes the file. Now the user of a FileStream object has control of the object’s behavior.

    But an interesting problem arises now: what should the FileStream’s Finalize method do when the FileStream object is collected? Obviously, the answer is nothing. In fact, there is no reason for the FileStream’s Finalize method to execute at all if the application has explicitly called the Close method. You know that Finalize methods are discouraged, and in this scenario you’re going to have the system call a Finalize method that should do nothing. It seems like there ought to be a way to suppress the system’s calling of the object’s Finalize method. Fortunately, there is. The System.GC type contains a static method, SuppressFinalize, that takes a single parameter, the address of an object.

    Figure 8 FileStream’s Type Implementation

    public class FileStream : Stream {

    public override void Close() {
    // Clean up this object: flush data and close file
    •••
    // There is no reason to Finalize this object now
    GC.SuppressFinalize(this);
    }

    protected override void Finalize() {
    Close();    // Clean up this object: flush data and close file
    }

    // Rest of FileStream methods go here
    •••
    }

    Figure 8 shows FileStream’s type implementation. When you call SuppressFinalize, it turns on a bit flag associated with the object. When this flag is on, the runtime knows not to move this object’s pointer to the freachable queue, preventing the object’s Finalize method from being called.
    Let’s examine another related issue. It is very common to use a StreamWriter object with a FileStream object.

    FileStream fs = new FileStream(“C:\SomeFile.txt”, FileMode.Open, FileAccess.Write, FileShare.Read);
    StreamWriter sw = new StreamWriter(fs);
    sw.Write (“Hi there”);

    // The call to Close below is what you should do
    sw.Close();
    // NOTE: StreamWriter.Close closes the FileStream. The FileStream
    //       should not be explicitly closed in this scenario
    Notice that the StreamWriter’s constructor takes a FileStream object as a parameter. Internally, the StreamWriter object saves the FileStream’s pointer. Both of these objects have internal data buffers that should be flushed to the file when you’re finished accessing the file. Calling the StreamWriter’s Close method writes the final data to the FileStream and internally calls the FileStream’s Close method, which writes the final data to the disk file and closes the file. Since StreamWriter’s Close method closes the FileStream object associated with it, you should not call fs.Close yourself.
    What do you think would happen if you removed the two calls to Close? Well, the garbage collector would correctly detect that the objects are garbage and the objects would get finalized. But, the garbage collector doesn’t guarantee the order in which the Finalize methods are called. So if the FileStream gets finalized first, it closes the file. Then when the StreamWriter gets finalized, it would attempt to write data to the closed file, raising an exception. Of course, if the StreamWriter got finalized first, then the data would be safely written to the file.

    How did Microsoft solve this problem? Making the garbage collector finalize objects in a specific order is impossible because objects could contain pointers to each other and there is no way for the garbage collector to correctly guess the order to finalize these objects. So, here is Microsoft’s solution: the StreamWriter type doesn’t implement a Finalize method at all. Of course, this means that forgetting to explicitly close the StreamWriter object guarantees data loss. Microsoft expects that developers will see this consistent loss of data and will fix the code by inserting an explicit call to Close.
    As stated earlier, the SuppressFinalize method simply sets a bit flag indicating that the object’s Finalize method should not be called. However, this flag is reset when the runtime determines that it’s time to call a Finalize method. This means that calls to ReRegisterForFinalize cannot be balanced by calls to SuppressFinalize. The code in Figure 9 demonstrates exactly what I mean.
    Figure 9 ReRegisterForFinalize and SuppressFinalize
    void method() {
    // The MyObj type has a Finalize method defined for it
    // Creating a MyObj places a reference to obj on the finalization table.
    MyObj obj = new MyObj();

    // Append another 2 references for obj onto the finalization table.
    GC.ReRegisterForFinalize(obj);
    GC.ReRegisterForFinalize(obj);

    // There are now 3 references to obj on the finalization table.

    // Have the system ignore the first call to this object’s Finalize
    // method.
    GC.SuppressFinalize(obj);

    // Have the system ignore the first call to this object’s Finalize
    // method.
    GC.SuppressFinalize(obj);   // In effect, this line does absolutely
    // nothing!

    obj = null;   // Remove the strong reference to the object.

    // Force the GC to collect the object.
    GC.Collect();

    // The first call to obj’s Finalize method will be discarded but
    // two calls to Finalize are still performed.
    }

    ReRegisterForFinalize and SuppressFinalize are implemented the way they are for performance reasons. As long as each call to SuppressFinalize has an intervening call to ReRegisterForFinalize, everything works. It is up to you to ensure that you do not call ReRegisterForFinalize or SuppressFinalize multiple times consecutively, or multiple calls to an object’s Finalize method can occur.

    Weak References

     

    When a root points to an object, the object cannot be collected because the application’s code can reach the object. When a root points to an object, it’s called a strong reference to the object. However, the garbage collector also supports weak references. Weak references allow the garbage collector to collect the object, but they also allow the application to access the object. How can this be? It all comes down to timing.

    If only weak references to an object exist and the garbage collector runs, the object is collected and when the application later attempts to access the object, the access will fail. On the other hand, to access a weakly referenced object, the application must obtain a strong reference to the object. If the application obtains this strong reference before the garbage collector collects the object, then the garbage collector can’t collect the object because a strong reference to the object exists. I know this all sounds somewhat confusing, so let’s clear it up by examining the code in Figure 1b.
    Figure 1b Strong and Weak References

    Void Method() {
    Object o = new Object();    // Creates a strong reference to the
    // object.

    // Create a strong reference to a short WeakReference object.
    // The WeakReference object tracks the Object.
    WeakReference wr = new WeakReference(o);

    o = null;    // Remove the strong reference to the object

    o = wr.Target;
    if (o == null) {
    // A GC occurred and Object was reclaimed.
    } else {
    // a GC did not occur and we can successfully access the Object
    // using o
    }
    }

    Why might you use weak references? Well, there are some data structures that are created easily, but require a lot of memory. For example, you might have an application that needs to know all the directories and files on the user’s hard drive. You can easily build a tree that reflects this information and as your application runs, you’ll refer to the tree in memory instead of actually accessing the user’s hard disk. This procedure greatly improves the performance of your application.
    The problem is that the tree could be extremely large, requiring quite a bit of memory. If the user starts accessing a different part of your application, the tree may no longer be necessary and is wasting valuable memory. You could delete the tree, but if the user switches back to the first part of your application, you’ll need to reconstruct the tree again. Weak references allow you to handle this scenario quite easily and efficiently.

    When the user switches away from the first part of the application, you can create a weak reference to the tree and destroy all strong references. If the memory load is low for the other part of the application, then the garbage collector will not reclaim the tree’s objects. When the user switches back to the first part of the application, the application attempts to obtain a strong reference for the tree. If successful, the application doesn’t have to traverse the user’s hard drive again.

    The WeakReference type offers two constructors:
    WeakReference(Object target);
    WeakReference(Object target, Boolean trackResurrection);
    The target parameter identifies the object that the WeakReference object should track. The trackResurrection parameter indicates whether the WeakReference object should track the object after it has had its Finalize method called. Usually, false is passed for the trackResurrection parameter and the first constructor creates a WeakReference that does not track resurrection.
    For convenience, a weak reference that does not track resurrection is called a short weak reference, while a weak reference that does track resurrection is called a long weak reference. If an object’s type doesn’t offer a Finalize method, then short and long weak references behave identically. It is strongly recommended that you avoid using long weak references. Long weak references allow you to resurrect an object after it has been finalized and the state of the object is unpredictable.

    Once you’ve created a weak reference to an object, you usually set the strong reference to the object to null. If any strong reference remains, the garbage collector will be unable to collect the object.

    To use the object again, you must turn the weak reference into a strong reference. You accomplish this simply by calling the WeakReference object’s Target property and assigning the result to one of your application’s roots. If the Target property returns null, then the object was collected. If the property does not return null, then the root is a strong reference to the object and the code may manipulate the object. As long as the strong reference exists, the object cannot be collected.

    Weak Reference Internals

     

    From the previous discussion, it should be obvious that WeakReference objects do not behave like other object types. Normally, if your application has a root that refers to an object and that object refers to another object, then both objects are reachable and the garbage collector cannot reclaim the memory in use by either object. However, if your application has a root that refers to a WeakReference object, then the object referred to by the WeakReference object is not considered reachable and may be collected.

    To fully understand how weak references work, let’s look inside the managed heap again. The managed heap contains two internal data structures whose sole purpose is to manage weak references: the short weak reference table and the long weak reference table. These two tables simply contain pointers to objects allocated within the managed heap.

    Initially, both tables are empty. When you create a WeakReference object, an object is not allocated from the managed heap. Instead, an empty slot in one of the weak reference tables is located; short weak references use the short weak reference table and long weak references use the long weak reference table.

    Once an empty slot is found, the value in the slot is set to the address of the object you wish to track the object’s pointer is passed to the WeakReference’s constructor. The value returned from the new operator is the address of the slot in the WeakReference table. Obviously, the two weak reference tables are not considered part of an application’s roots or the garbage collector would not be able to reclaim the objects pointed to by the tables.

    Now, here’s what happens when a garbage collection (GC) runs:

    • The garbage collector builds a graph of all the reachable objects.
    • The garbage collector scans the short weak reference table. If a pointer in the table refers to an object that is not part of the graph, then the pointer identifies an unreachable object and the slot in the short weak reference table is set to null.
    • The garbage collector scans the finalization queue. If a pointer in the queue refers to an object that is not part of the graph, then the pointer identifies an unreachable object and the pointer is moved from the finalization queue to the freachable queue. At this point, the object is added to the graph since the object is now considered reachable.
    • The garbage collector scans the long weak reference table. If a pointer in the table refers to an object that is not part of the graph (which now contains the objects pointed to by entries in the freachable queue), then the pointer identifies an unreachable object and the slot is set to null.
    • The garbage collector compacts the memory, squeezing out the holes left by the unreachable objects.
      Once you understand the logic of the garbage collection process, it’s easy to understand how weak references work. Accessing the WeakReference’s Target property causes the system to return the value in the appropriate weak reference table’s slot. If null is in the slot, the object was collected.

    A short weak reference doesn’t track resurrection. This means that the garbage collector sets the pointer to null in the short weak reference table as soon as it has determined that the object is unreachable. If the object has a Finalize method, the method has not been called yet so the object still exists. If the application accesses the WeakReference object’s Target property, then null will be returned even though the object actually still exists.

    A long weak reference tracks resurrection. This means that the garbage collector sets the pointer to null in the long weak reference table when the object’s storage is reclaimable. If the object has a Finalize method, the Finalize method has been called and the object was not resurrected.

    Generations

     
    The GC developers are tweaking the garbage collector to improve its performance. One feature of the garbage collector that exists purely to improve performance is called generations. A generational garbage collector (also known as an ephemeral garbage collector) makes the following assumptions:

    • The newer an object is, the shorter its lifetime will be.
    • The older an object is, the longer its lifetime will be.
    • Newer objects tend to have strong relationships to each other and are frequently accessed around the same time.
    • Compacting a portion of the heap is faster than compacting the whole heap.
    • When initialized, the managed heap contains no objects. Objects added to the heap are said to be in generation 0, as you can see in Figure 8. Stated simply, objects in generation 0 are young objects that have never been examined by the garbage collector.

     

     

    Figure 8 Generation 0

     

    Now, if more objects are added to the heap, the heap fills and a garbage collection must occur. When the garbage collector analyzes the heap, it builds the graph of garbage (shown here in purple) and non-garbage objects. Any objects that survive the collection are compacted into the left-most portion of the heap. These objects have survived a collection, are older, and are now considered to be in generation 1 (see Figure 9).

     

    Figure 9 Generations 0 and 1

    As even more objects are added to the heap, these new, young objects are placed in generation 0. If generation 0 fills again, a GC is performed. This time, all objects in generation 1 that survive are compacted and considered to be in generation 2 (see Figure 10). All survivors in generation 0 are now compacted and considered to be in generation 1. Generation 0 currently contains no objects, but all new objects will go into generation 0.


     

    Figure 10 Generations 0, 1, and 2

    Currently, generation 2 is the highest generation supported by the runtime’s garbage collector. When future collections occur, any surviving objects currently in generation 2 simply stay in generation 2.

    Generational GC Performance Optimizations

     
    As I stated earlier, generational garbage collecting improves performance. When the heap fills and a collection occurs, the garbage collector can choose to examine only the objects in generation 0 and ignore the objects in any greater generations. After all, the newer an object is, the shorter its lifetime is expected to be. So, collecting and compacting generation 0 objects is likely to reclaim a significant amount of space from the heap and be faster than if the collector had examined the objects in all generations.
    This is the simplest optimization that can be obtained from generational GC. A generational collector can offer more optimizations by not traversing every object in the managed heap. If a root or object refers to an object in an old generation, the garbage collector can ignore any of the older objects’ inner references, decreasing the time required to build the graph of reachable objects. Of course, it is possible that an old object refers to a new object. So that these objects are examined, the collector can take advantage of the system’s write-watch support (provided by the Win32® GetWriteWatch function in Kernel32.dll). This support lets the collector know which old objects (if any) have been written to since the last collection. These specific old objects can have their references checked to see if they refer to any new objects.

    If collecting generation 0 doesn’t provide the necessary amount of storage, then the collector can attempt to collect the objects from generations 1 and 0. If all else fails, then the collector can collect the objects from all generations 2, 1, and 0. The exact algorithm used by the collector to determine which generations to collect is one of those areas that Microsoft will be tweaking forever.

    Most heaps (like the C runtime heap) allocate objects wherever they find free space. Therefore, if I create several objects consecutively, it is quite possible that these objects will be separated by megabytes of address space. However, in the managed heap, allocating several objects consecutively ensures that the objects are contiguous in memory.

    One of the assumptions stated earlier was that newer objects tend to have strong relationships to each other and are frequently accessed around the same time. Since new objects are allocated contiguously in memory, you gain performance from locality of reference. More specifically, it is highly likely that all the objects can reside in the CPU’s cache. Your application will access these objects with phenomenal speed since the CPU will be able to perform most of its manipulations without having cache misses which forces RAM access.

    Microsoft’s performance tests show that managed heap allocations are faster than standard allocations performed by the Win32 HeapAlloc function. These tests also show that it takes less than 1 millisecond on a 200Mhz Pentium to perform a full GC of generation 0. It is Microsoft’s goal to make GCs take no more time than an ordinary page fault.

    Direct Control with System.GC

     

    The System.GC type allows your application some direct control over the garbage collector. For starters, you can query the maximum generation supported by the managed heap by reading the GC.MaxGeneration property. Currently, the GC.MaxGeneration property always returns 2.

    It is also possible to force the garbage collector to perform a collection by calling one of the two methods shown here:
    void GC.Collect(Int32 Generation)
    void GC.Collect()
    The first method allows you to specify which generation to collect. You may pass any integer from 0 to GC.MaxGeneration, inclusive. Passing 0 causes generation 0 to be collected; passing 1 causes generation 1 and 0 to be collected; and passing 2 causes generation 2, 1, and 0 to be collected. The version of the Collect method that takes no parameters forces a full collection of all generations and is equivalent to calling:
    GC.Collect(GC.MaxGeneration);
    Under most circumstances, you should avoid calling any of the Collect methods; it is best to just let the garbage collector run on its own accord. However, since your application knows more about its behaviour than the runtime does, you could help matters by explicitly forcing some collections. For example, it might make sense for your application to force a full collection of all generations after the user saves his data file. I imagine Internet browsers performing a full collection when pages are unloaded. You might also want to force a collection when your application is performing other lengthy operations; this hides the fact that the collection is taking processing time and prevents a collection from occurring when the user is interacting with your application.

    The GC type also offers a WaitForPendingFinalizers method. This method simply suspends the calling thread until the thread processing the freachable queue has emptied the queue, calling each object’s Finalize method. In most applications, it is unlikely that you will ever have to call this method.

    Lastly, the garbage collector offers two methods that allow you to determine which generation an object is currently in:
    Int32 GetGeneration(Object obj)
    Int32 GetGeneration(WeakReference wr)
    The first version of GetGeneration takes an object reference as a parameter, and the second version takes a WeakReference reference as a parameter. Of course, the value returned will be somewhere between 0 and GC.MaxGeneration, inclusive.

    The code in Figure 5a will help you understand how generations work. It also demonstrates the use of the garbage collection methods just discussed.
    Figure 5a GC Methods Demonstration

     

    private static void GenerationDemo() {
    // Let’s see how many generations the GCH supports (we know it’s 2)
    Display(“Maximum GC generations: ” + GC.MaxGeneration);

    // Create a new BaseObj in the heap
    GenObj obj = new GenObj(“Generation”);

    // Since this object is newly created, it should be in generation 0
    obj.DisplayGeneration();    // Displays 0

    // Performing a garbage collection promotes the object’s generation
    Collect();
    obj.DisplayGeneration();    // Displays 1

    Collect();
    obj.DisplayGeneration();    // Displays 2

    Collect();
    obj.DisplayGeneration();    // Displays 2   (max generation)

    obj = null;         // Destroy the strong reference to this object

    Collect(0);         // Collect objects in generation 0
    WaitForPendingFinalizers();    // We should see nothing

    Collect(1);         // Collect objects in generation 1
    WaitForPendingFinalizers();    // We should see nothing

    Collect(2);         // Same as Collect()
    WaitForPendingFinalizers();    // Now, we should see the Finalize
    // method run

    Display(-1, “Demo stop: Understanding Generations.”, 0);
    }

    Performance for Multithreaded Applications

    In the previous section, I explained the GC algorithm and optimizations. However, there was a big assumption made during that discussion: only one thread is running. In the real world, it is quite likely that multiple threads will be accessing the managed heap or at least manipulating objects allocated within the managed heap. When one thread sparks a collection, other threads must not access any objects (including object references on its own stack) since the collector is likely to move these objects, changing their memory locations.

    So, when the garbage collector wants to start a collection, all threads executing managed code must be suspended. The runtime has a few different mechanisms that it uses to safely suspend threads so that a collection may be done. The reason there are multiple mechanisms is to keep threads running as long as possible and to reduce overhead as much as possible. I don’t want to go into all the details here, but suffice it to say that Microsoft has done a lot of work to reduce the overhead involved with performing a collection. Microsoft will continue to modify these mechanisms over time to help ensure efficient garbage collections.

    The following paragraphs describe a few of the mechanisms that the garbage collector employs when applications have multiple threads:
    Fully Interruptible Code When a collection starts, the collector suspends all application threads. The collector then determines where a thread got suspended and using tables produced by the just-in-time (JIT) compiler, the collector can tell where in a method the thread stopped, what object references the code is currently accessing, and where those references are held (in a variable, CPU register, and so on).

    Hijacking The collector can modify a thread’s stack so that the return address points to a special function. When the currently executing method returns, this special function will execute, suspending the thread. Stealing the thread’s execution path this way is referred to as hijacking the thread. When the collection is complete, the thread will resume and return to the method that originally called it.
    Safe Points As the JIT compiler compiles a method, it can insert calls to a special function that checks if a GC is pending. If so, the thread is suspended, the GC runs to completion, and the thread is then resumed. The position where the compiler inserts these method calls is called a GC safe point.

    Note that thread hijacking allows threads that are executing unmanaged code to continue execution while a garbage collection is occurring. This is not a problem since unmanaged code is not accessing objects on the managed heap unless the objects are pinned and don’t contain object references. A pinned object is one that the garbage collector is not allowed to move in memory. If a thread that is currently executing unmanaged code returns to managed code, the thread is hijacked and is suspended until the GC completes.

    In addition to the mechanisms I just mentioned, the garbage collector offers some additional improvements that enhance the performance of object allocations and collections when applications have multiple threads.

    Synchronization-free Allocations On a multiprocessor system, generation 0 of the managed heap is split into multiple memory arenas using one arena per thread. This allows multiple threads to make allocations simultaneously so that exclusive access to the heap is not required.
    Scalable Collections On a multiprocessor system running the server version of the execution engine (MSCorSvr.dll), the managed heap is split into several sections, one per CPU. When a collection is initiated, the collector has one thread per CPU; all threads collect their own sections simultaneously. The workstation version of the execution engine (MSCorWks.dll) doesn’t support this feature.

    Garbage-collecting Large Objects

     
    There is one more performance improvement that you might want to be aware of. Large objects (those that are 20,000 bytes or larger) are allocated from a special large object heap. Objects in this heap are finalized and freed just like the small objects I’ve been talking about. However, large objects are never compacted because shifting 20,000-byte blocks of memory down in the heap would waste too much CPU time.

    Note that all of these mechanisms are transparent to your application code. To you, the developer, it looks like there is just one managed heap; these mechanisms exist simply to improve application performance.

    Monitoring Garbage Collections

     

    The runtime team at Microsoft has created a set of performance counters that provide a lot of real-time statistics about the runtime’s operations. You can view these statistics via the Windows 2000 System Monitor ActiveX ® control. The easiest way to access the System Monitor control is to run PerfMon.exe and select the + toolbar button, causing the Add Counters dialog box to appear (see Figure 11).


     

    Figure 11 Adding Performance Counters

     

    To monitor the runtime’s garbage collector, select the COM+ Memory Performance object. Then, you can select a specific application from the instance list box. Finally, select the set of counters that you’re interested in monitoring and press the Add button followed by the Close button. At this point, the System Monitor will graph the selected real-time statistics. Figure 12 describes the function of each counter.

    Figure 12 Counters to Monitor

     

    Counter Description
    # Bytes in all Heaps Total bytes in heaps for generations 0, 1, and 2 and from the large object heap. This indicates how much memory the garbage collector is using to store allocated objects.
    # GC Handles Total number of current GC handles.
    # Gen 0 Collections Number of collections of generation 0 (youngest) objects.
    # Gen 1 Collections Number of collections of generation 1 objects.
    # Gen 2 Collections Number of collections of generation 2 (oldest) objects.
    # Induced GC Total number of times the GC was run because of an explicit call (such as from the Classlibs) instead of during an allocation.
    # Pinned Objects Not yet implemented.
    # of Sink Blocks in use Synchronization primitives use sink blocks. Sink block data belongs to an object and is allocated on demand.
    # Total committed Bytes Total committed bytes from all heaps.
    % Time in GC Total time since the last sample spent performing garbage collection, divided by total time since the last sample.
    Allocated Bytes/sec Rate of bytes per second allocated by the garbage collector. This is only updated at a garbage collection, not at each allocation. Since it is a rate, time between GCs will be 0.
    Finalization Survivors Number of garbage-collected classes that survive because their finalizer creates a reference to them.
    Gen 0 heap size Size of generation 0 (youngest) heap in bytes.
    Gen 0 Promoted Bytes/Sec Bytes per second that are promoted from generation 0 (youngest) to generation 1. Memory is promoted when it survives a garbage collection.
    Gen 1 heap size Size of generation 1 heap in bytes.
    Gen 1 Promoted Bytes/Sec Bytes per second that are promoted from generation 1 to generation 2 (oldest). Memory is promoted when it survives a garbage collection. Nothing is promoted from generation 2, since it is the oldest.
    Gen 2 heap size Size of generation 2 (oldest) heap in bytes.
    Large Object Heap size Size of the Large Object heap in bytes.
    Promoted Memory from Gen 0 Bytes of memory that survive garbage collection and are promoted from generation 0 to generation 1.
    Promoted Memory from Gen 1 Bytes of memory that survive garbage collection and are promoted from generation 1 to generation 2.

     

    Garbage Collection v4.0

    The .NET garbage collector is one of the areas of the .NET Framework that is extremely important and probably one of the least understood. There are a lot of articles written about it and there have been very few changes since .NET 1.0 was first released. (There have been changes with almost each release, but they have been relatively minor.)
    With .NET 4.0, however, there are some fairly substantial changes to the GC that will have some interesting performance implications (in a good way).
    For a quick review, the GC in .NET is a generational garbage collector with 3 generations. Generation 0 and 1 collections are very fast since the segment (called the ephemeral segment) is small while Generation 2 collections can be relatively slow.
    The changes in the server GC will probably only affect a small number of applications. However, the changes to the workstation GC (which is the default mode) will affect almost all .NET applications. In CLR 4, you can now subscribe to an event to be notified before a Generation 2 or Large Object Heap collection.
    try
    {
    // Register for a set of notifications.
    // Parameters require tuning. First is
    // for Gen2, second, Large Object Heap
    GC.RegisterForFullGCNotification(10, 10);

    // Start a thread using WaitForFullGCProc
    Thread thWaitForFullGC = new Thread(new ThreadStart(WaitForFullGCProc));
    thWaitForFullGC.Start();
    In all .NET Framework versions from 3.5SP1 and earlier, workstation GC used a concurrent collection method. This means that the GC can do most, but not all, of a Generation 2 collection without pausing managed code. It can’t, however, do a Generation 0 and Generation 1 collection at the same time as a Generation 2 collection.
    CLR 4.0 changes that to support background collection, which can do a Generation 0 and Generation 1 collection at the same time as a Generation 2 collection. This means that now only unusual circumstances should lead to long latency times.
    Background GC is an evolution to concurrent GC. The significance of background GC is we can do ephemeral GCs while a background GC is in progress if needed. As with concurrent GC, background GC is also only applicable to full GCs and ephemeral GCs are always done as blocking GCs, and a background GC is also done on its dedicated GC thread. The ephemeral GCs done while a background GC is in progress are called foreground GCs.

    *The credit for above mentioned article goes to Jeffrey Richter for publishing the contents on msdn magazine and Scott Dorman.

  • .Net CTS (Common Type System) Overview

    In this article you will learn what is CTS, primitive types, value type , reference type, boxing, unboxing, blittable , non nlittable types and how it impact performance.

    In Microsoft’s .NET Framework, the Common Type System (CTS) is a standard that specifies how Type definitions and specific values of Types are represented in computer memory. It is intended to allow programs written in different programming languages to easily share information. The CTS specifies no particular syntax or keywords, but instead defines a common set of types that can be used with many different language syntaxes. 

    For example CTS defines System.Int32 – 4 byte integer
    C# defines int as an alias of System.Int32
    string -> System.String
    object -> System.Object
     

    The specification for the CTS is contained in Ecma standard 335, “Common Language Infrastructure (CLI).” The CLI and the CTS were created by Microsoft, and the Microsoft .NET framework is an implementation of the standard.
    Functions of CTS 

    • To establish a framework that helps enable cross-language integration, type safety, and high performance code execution. 
    • To provide an object-oriented model that supports the complete implementation of many programming languages. 
    • To define rules that languages must follow, which helps ensure that objects written in different languages can interact with each other. 
    • The CTS also defines the rules that ensures that the data types of objects written in various languages are able to interact with each other. 
    • Languages supported by .NET can implement all or some common data types.

    Primitive Types

     
    Certain data types are used so commonly that many compilers allow your code to manipulate them using simplified syntax. For example, you could allocate an integer using the following syntax in C#:
    int a = new int(5);
    But I’m sure you’ll agree that declaring and initializing an integer using this syntax is rather cumbersome. Fortunately, many compilers (including C#) allow you to use syntax similar to the following instead:

    int a = 5;
    This certainly makes the code more readable. And, of course, the intermediate language (IL) that is generated when using either syntax is identical. Any data types directly supported by the compiler are called primitive types. Primitive types map directly to types that exist in the base class library. For example, in C# an int maps directly to the System.Int32 type.

    C# Primitive Type  BCL Type  Description 
    sbyte  System.SByte  Signed 8-bit value 
    byte  System.Byte  Unsigned 8-bit value 
    short  System.Int16  Signed 16-bit value 
    ushort  System.UInt16  Unsigned 16-bit value 
    int  System.Int32  Signed 32-bit value 
    uint  System.UInt32  Unsigned 32-bit value 
    long  System.Int64  Signed 64-bit value 
    ulong  System.UInt64  Unsigned 64-bit value 
    char  System.Char  16-bit Unicode character 
    float  System.Single  IEEE 32-bit float 
    double  System.Double  IEEE 64-bit float 
    bool  System.Boolean  A True/False value 
    decimal  System.Decimal  96-bit signed integer times 100 through 1028 (common for financial calculations where rounding errors can’t be tolerated) 
    string  System.String  String type 
    object  System.Object  Base of all types 

    Reference and Value Types

    The common type system supports two general categories of types: Value Type (lightweight types) & Reference Type.
    Reference types  : When an object is allocated from the managed heap, the new operator returns the memory address of the object. You usually store this address in a variable. This is called a reference type variable because the variable does not actually contain the object’s bits; instead, the variable refers to the object’s bits.

    There are some performance issues to consider when working with reference types. First, the memory must be allocated from the managed heap, which could force a garbage collection to occur. Second, reference types are always accessed via their pointers. So every time your code references any member of an object on the heap, code must be generated and executed to dereference the pointer in order to perform the desired action. This adversely affects both size and speed. Reference types can be self-describing types, pointer types, or interface types. The type of a reference type can be determined from values of self-describing types. Self-describing types are further split into arrays and class types. The class types are user-defined classes, boxed value types, and delegates.
    Eg. 

     // Reference Type (because of ‘class’)
     class  RectRef { public int x, y, cx, cy; }
     

    Value types : Value type objects cannot be allocated on the garbage-collected heap, and the variable representing the object does not contain a pointer to an object; the variable contains the object itself. Since the variable contains the object, a pointer does not have to be dereferenced in order to manipulate the object. This, of course, improves performance.Value types are either allocated on the stack or allocated inline in a structure. Value types can be built-in (implemented by the runtime), user-defined, or enumerations.
    Eg.
     // Value type (because of ‘struct’)
     struct RectVal { public int x, y, cx, cy; }
     

    RectRef rr1 = new RectRef();  // Allocated in heap
    RectVal rv1;                  // Allocated on stack (new optional)
    rr1.x = 10;                   // Pointer dereference
    rv1.x = 10;                   // Changed on stack 

    RectRef rr2 = rr1;            // Copies pointer only
    RectVal rv2 = rv1;            // Allocate on stack & copies members
    rr1.x = 20;                   // Changes rr1 and rr2
    rv1.x = 20;                   // Changes rv1, not rv2
     

    The Rectangle type is declared using struct instead of the more common class. In C#, a type declared using struct is a value type, while types declared using class are reference types. 

    When possible, you should use value types instead of reference types because your application’s performance will be better. In particular, you should declare a type as a value type if all of the following are true: 

    • The type acts like a primitive type.
    • The type doesn’t need to inherit from any other type.
    • The type will not have any other types derived from it.
    • Objects of the type are not frequently passed as method arguments since this would cause frequent memory copy operations, hurting performance. The next section on boxing and unboxing will explain this in more detail.

    The main advantage of value types is that they are not allocated in the managed heap. Of course, value types have several limitations compared with reference types. Here are some of the ways in which value types and reference types differ.Value type objects have two representations: an unboxed form and a boxed form. Reference types are always in a boxed form. Value types are implicitly derived from System.ValueType. This type offers the same methods as defined by System.Object. However, System.ValueType overrides the Equals method so that it returns true if the values of the two objects’ instance fields match. In addition, System.ValueType overrides the GetHashCode method so that it produces a hash code value using an algorithm that takes into account the values in the objects’ instance fields. When defining your own value types, it is highly recommended that you override and provide explicit implementations for the Equals and GetHashCode methods.
    Since you cannot declare a new value type or a new reference type using a value type as a base class, value types should not have virtual functions, cannot be abstract, and are implicitly sealed (a sealed type cannot be used as the base of a new type).
    Reference type variables contain the memory address of objects in the heap. By default, when a reference type variable is created, it is initialized to null, indicating that the reference type variable doesn’t currently point to a valid object. Attempting to use a null reference type variable causes a NullReferenceException exception. By contrast, value type variables always contain a value of the underlying type. By default, all members of the value type are initialized to zero. It is not possible to generate a NullReferenceException exception when accessing a value type. 

    When you assign a value type variable to another value type variable, a copy of the value is made. When you assign a reference type variable to another reference type variable, only the memory address is copied. Because of the previous point, two or more reference type variables may refer to a single object in the heap. This allows operations on one variable to affect the object referenced by the other variable. On the other hand, value type variables each have their own copy of the object’s data, and it is not possible for operations on one value type variable to affect another.
     

    There are rare situations when the runtime must initialize a value type and is unable to call its default constructor. For example, this can happen when a thread local value type must be allocated and initialized when an unmanaged thread first executes managed code. In this situation, the runtime can’t call the type’s constructor but still ensures that all members are initialized to zero or null. For this reason, it is recommended that you don’t define a parameterless constructor on a value type. In fact, the C# compiler (and others) consider this an error and won’t compile the code. This problem is rare, and it never occurs on reference types. There are no restrictions on parameterized constructors for both value types and reference types.
     

    Since unboxed value types are not allocated on the heap, the storage allocated for them is freed as soon as the method that defines an instance of the type is no longer active. This also means that unboxed value type objects cannot receive a notification when their memory is reclaimed. However, a boxed value type will have its Finalize method called when it is garbage-collected. You are strongly discouraged from implementing a value type with a Finalize method. Like a parameterless constructor, C# considers this an error and will not compile the source code.
    Boxing and Unboxing

     
    There are many situations in which it is convenient to treat a value type as a reference type. Let’s say that you wanted to create an ArrayList object (a type defined in the System.Collections namespace) to hold a set of Points. The code might look like
    // Declare a value type
    struct Point {
       public int x, y;
    }
     

    ArrayList a = new ArrayList();
       for (int i = 0; i < 10; i++) {
          Point p;                // Allocate a Point (not in the heap)
          p.x = p.y = i;          // Initialize the members in the value type
          a.Add(p);               // Box the value type and add the
                                  // reference to the array
       }
     

    When the Add method is called, memory is allocated in the heap for a Point object. The members currently residing in the Point value type (p) are copied into the newly allocated Point object. The address of the Point object (a reference type) is returned and is then passed to the Add method. The Point object will remain in the heap until it is garbage-collected. The Point value type variable (p) can be reused or freed since the ArrayList never knows anything about it. Boxing enables a unified view of the type system, where a value of any type can ultimately be treated as an object.
     The opposite of boxing is, of course, unboxing. Unboxing retrieves a reference to the value type (data fields) contained within an object. Internally, the following is what happens when a reference type is unboxed: 

    • The common language runtime first ensures that the reference type variable is not null and that it refers to an object that is a boxed value of the desired value type. If either test fails, then an InvalidCastException exception is generated.
    • If the types do match, then a pointer to the value type contained inside the object is returned. The value type that this pointer refers to does not include the usual overhead associated with a true object: a pointer to a virtual method table and a sync block.

    Note that boxing always creates a new object and copies the unboxed value’s bits to the object. On the other hand, unboxing simply returns a pointer to the data within a boxed object: no memory copy occurs. However, it is commonly the case that your code will cause the data pointed to by the unboxed reference to be copied anyway.The following code demonstrates boxing and unboxing:

    public static void Main() {
       Int32 v = 5;    // Create an unboxed value type variable
       Object o = v;   // o refers to a boxed version of v
       v = 123;        // Changes the unboxed value to 123
     

       Console.WriteLine(v + “, ” + (Int32) o);    // Displays “123, 5”
    }
     

    From this code, can you guess how many boxing operations occur? You might be surprised to discover that the answer is three! Let’s analyze the code carefully to really understand what’s going on.
    First, an Int32 unboxed value type (v) is created and initialized to 5. Then an Object reference type (o) is created and it wants to point to v. But reference types must always point to objects in the heap, so C# generated the proper IL code to box v and stored the address of the boxed version of v in o. Now 123 is unboxed and the referenced data is copied into the unboxed value type v; this has no effect on the boxed version of v, so the boxed version keeps its value of 5. Note that this example shows how o is unboxed (which returns a pointer to the data in o), and then the data in o is memory copied to the unboxed value type v. 

    Now, you have the call to WriteLine. WriteLine wants a String object passed to it but you don’t have a String object. Instead, you have these three items: an Int32 unboxed value type (v), a string, and an Int32 reference (or boxed) type (o). These must somehow be combined to create a String. To accomplish this, the C# compiler generates code that calls the String object’s static Concat method. There are several overloaded versions of Concat. All of them perform identically; the difference is in the number of parameters. Since you want to format a string from three items, the compiler chooses the following version of the Concat method:
    public static String Concat(Object arg0, Object arg1, Object arg2);
     

    For the first parameter, arg0, v is passed. But v is an unboxed value parameter and arg0 is an Object, so v must be boxed and the address to the boxed v is passed for arg0. For the arg1 parameter, the address of the “, ” string is passed, identifying the address of a String object. Finally, for the arg2 parameter, o (a reference to an Object) was cast to an Int32. This creates a temporary Int32 value type that receives the unboxed version of the value currently referred to by o. This temporary Int32 value type must be boxed once again with the memory address being passed for Concat’s arg2 parameter.
     

    Once Concat is called, it calls each of the specified object’s ToString methods and concatenates each object’s string representation. The String object returned from Concat is then passed to WriteLine to show the final result.

    I should point out that the generated IL code would be more efficient if the call to WriteLine were written as follows:
    Console.WriteLine(v + “, ” + o);    // Displays “123, 5”
    This line is identical to the previous version except that I’ve removed the (Int32) cast that preceded the variable o. This code is more efficient because o is already a reference type to an Object and its address may simply be passed to the Concat method. So, removing the cast saved both an unbox and a box operation.
     Here is another example that demonstrates boxing and unboxing:


    public static void Main() {
       Int32 v = 5;           // Create an unboxed value type variable
       Object o = v;          // o refers to the boxed version of v 

       v = 123;               // Changes the unboxed value type to 123
       Console.WriteLine(v);  // Displays “123” 

       v = (Int32) o;         // Unboxes o into v
       Console.WriteLine(v);  // Displays “5”
    }  

    How many boxing operations do you count in this code? The answer is one. There is only one boxing operation because there is a WriteLine method that accepts an Int32 as a parameter:
    public static void WriteLine(Int32 value);

    *Note : Stack or Heap

    It’s more complicated than you might think. Even your claim that “value types are allocated on the stack” isn’t correct. For example:

    class Foo
    {
        int x;
    }
    

    int is a value type, but the value for x will always be on the heap because it will be stored with the rest of the data for the instance of Foo which is a class.

    Remember the rule, Reference types always goes to the Heap, whereas Value Types always go where they were declared. If a Value Type is declared outside of a method, but inside a Reference Type it will be placed within the Reference Type on the Heap.

    you may be interested in article about C# heap/stack memory , but you might also want to read Eric Lippert’s blog post on “The stack is an implementation detail”. and here is another simple but powerfull article on stack vs heap

    Blittable/Non Blittable types 

    Blittable types are defined as having an identical presentation in memory for managed and unmanaged (COM) environments, and can be directly shared. Understanding the difference between blittable and non-blittable types can aid in using COM Interop or P/Invoke, two techniques for interoperability in .NET applications.
    By pinning the data in memory, the garbage collector will be prevented from moving it , allowing it to be shared in-place with the unmanaged application.This means that both managed and unmanaged code will alter the memory locations of these types in a consistent manner, and much less effort is required by the marshaler to maintain data integrity. The following are some examples of blittable types available in the .NET framework:

    • System.Byte
    • System.SByte
    • System.Int16
    • System.UInt16
    • System.Int32
    • System.UInt32
    • System.Int64
    • System.IntPtr
    • System.UIntPtr

    Additionally, one-dimensional arrays of these types as well as complex types containing only fields of these types are blittable.
    If a type is not one of the blittable types, then it is classified as non-blittable. The reason a type is considered non-blittable is that for one representation in managed memory, it may have several potential representations in unmanaged memory or vice-versa. Alternatively, there may be exactly one representation for the type in both managed and unmanaged memory. It is also often the case that there simply is no representation on one side or the other. The following are some commonly-used non-blittable types in the .NET framework:

    • System.Boolean
    • System.Char
    • System.Object
    • System.String

    There are many more blittable and non-blittable types, and user-defined types may fit in either category depending on how they are defined

    Interoperability overview


    Interoperability can be bidirectional sharing of data and methods between unmanaged code and managed .NET code. .NET provides two ways of interoperating between the two: COM Interop and P/Invoke. Though the methodology is different, in both cases marshalling (conversion between representations of data, formats for calling functions and formats for returning values) must take place. COM Interop deals with this conversion between managed code and COM objects, whereas P/Invoke handles interactions between managed code and Win32 code. The concept of blittable and non-blittable data types applies to both — specifically to the problem of converting data between managed and unmanaged memory. This marshalling is performed by the interop marshaller, which is invoked automatically by the CLR when needed.

  • .Net CLR Internals

    The CLR is described as the “execution engine” of .NET. It provides the environment within which the programs run. It’s this CLR that manages the execution of programs and provides core services, such as code compilation, memory allocation, thread management, and garbage collection. Through the Common Type System (CTS), it enforces strict type safety, and it ensures that the code is executed in a safe environment by enforcing code access security. The software version of .NET is actually the CLR version.

    The European Computer Manufacturers Association (ECMA) standard has defines the Common Language Specification (CLS); this enforces that software development languages should be interoperable between them. The code written in a CLS should be compliant with the code written in another CLS-compliant language. Because the code supported by CLS-compliant language should be compiled into an intermediate language (IL) code. The CLR  engine executes the IL code. This ensures interoperability between CLS-compliant languages.

    The ECMA standard, Common Language Infrastructure (CLI), defines the specifications for the infrastructure that the IL code needs for execution.The CLR is Implementation of CLI. The CLI provides a common type system (CTS) and services such as type safety, managed code execution and side by side execution.

    In my previous article (.Net CLR Overview) we have seen how CLR is get loaded when user executes .net executable on windows (say) platform.

    There are many components in CLR which are used to do specific tasks or functions of CLR.

    The above diagram show the various components of .Net CLR , Each component is responsible for specific functionality mentioned below.

    • Class Loader : It is used to load all the classes (MSIL Code) at runtime into CLR. The class loader component of the CLR uses metadata to locate specific classes within assemblies, either locally or across networks.
    • MSIL to Native compiler : It is a JIT (Just In Time) compiler it will convert MSIL code to native code.
    • Code Manager : It manages the code during execution.
    • Garbage Collector : Memory allocation and Garbage collector, this performs automatic memory management.
    • Security engine : this enforces security restrictions as code level security folder level and machine level security using tools provided by Microsoft .NET and using .NET Framework setting under control panel.
    • Type Checker : It enforces strict type checking.
    • Thread Support : It provides multithreading support to .Net applications.
    • Exception Manager : It provides mechanisum to handle execptions at runtime.
    • Debug Engine : Allows developer to debug different types of applications.
    • Com Marshaler : Allows .NET applications to exchange data with COM applications.
    • Base Class library support : Which provides the classes (types) that the applications need at run time.

    How it works

    When the .NET program is compiled, the output of the compiler is not an executable file but a file that contains a special type of code called  the Microsoft Intermediate Language (MSIL), which is a low-level set of instructions understood by the common language run time. This MSIL defines a set of portable instructions that are independent of any specific CPU. It’s the job of the CLR to translate this Intermediate code into a executable code when the program is executed making the program to run in any environment for which the CLR is implemented. And that’s how the .NET Framework achieves Portability. This MSIL is turned into executable code using a JIT (Just In Time) complier. The process goes like this, when .NET programs are executed, the CLR activates the JIT complier. The JIT complier converts MSIL into native code on a demand basis as each part of the program is needed. Thus the program executes as a native code even though it is compiled into MSIL making the program to run as fast as it would if it is compiled to native code but achieves the portability benefits of MSIL.

    We will cover CLR core features like garbage collector, Thread support,Exception manager,Debug engine,Security engine in next articles.

  • .Net CLR Overview

    The Microsoft .NET Framework is a software framework that can be installed on computers running Microsoft Windows operating systems. It includes a large library of coded solutions to common programming problems and a virtual machine that manages the execution of programs written specifically for the framework. The .NET Framework is a Microsoft offering and is intended to be used by most new applications created for the Windows platform.

    The framework’s Base Class Library provides a large range of features including user interface, data access, database connectivity, cryptography, web application development, numeric algorithms, and network communications. The class library is used by programmers, who combine it with their own code to produce applications.

    Programs written for the .NET Framework execute in a software environment that manages the program’s runtime requirements. Also part of the .NET Framework, this runtime environment is known as the Common Language Runtime (CLR). The CLR provides the appearance of an application virtual machine so that programmers need not consider the capabilities of the specific CPU that will execute the program. The CLR also provides other important services such as security, memory management, and exception handling. The class library and the CLR together constitute the .NET Framework.

    The Common Language Runtime (CLR) is the foundation of the .NET Framework. CLR act as an agent that manages code at execution time, providing core services such as memory management, thread management, and remoting, while also enforcing strict type safety and facilitates with code accuracy that ensure security and robustness. The concept of code management is a fundamental principle of the CLR. Code that targets the CLR is known as managed code, while code that does not target the CLR is known as unmanaged code.

    Developers using the CLR write code in a language such as C# or VB.NET. At compile time, a .NET compiler converts such code into CIL code. At runtime, the CLR’s just-in-time compiler converts the CIL code into code native to the operating system. Alternatively, the CIL code can be compiled to native code in a separate step prior to runtime by using the Native Image Generator (NGEN). This speeds up all later runs of the software as the CIL-to-native compilation is no longer necessary.

    •  The .NET Framework provides a run-time environment called the common language runtime, which runs the code and provides services that make the development process easier.
    • The core runtime engine in the Microsoft .NET Framework for executing applications.
    • The common language runtime supplies managed code with services such as cross-language integration, code access security, object lifetime management, resouce management, type safety, pre-emptive threading, metadata services (type reflection), and debugging and profiling support.
    • The CLR is a multi-language execution environment. There are currently over 15 compilers being built by Microsoft and other companies that produce code that will execute in the CLR.
    • It is Microsoft’s implementation of the Common Language Infrastructure (CLI) standard, which defines an execution environment for program code.
    • In the CLR, code is expressed in a form of bytecode called the Common Intermediate Language (CIL, previously known as MSIL—Microsoft Intermediate Language).
    • You can create source code files using any programming language that supports the CLR. Then, you
      use the corresponding compiler to check syntax and analyze the source code. Regardless of which compiler you use, the
      result is a managed module. A managed module is a standard Windows portable executable (PE) file that requires the
      CLR to execute.

    A Managed Module is composed of the following parts:

    PE header : This is the standard Windows PE file header, which is similar to the Common Object File Format (COFF) header. The PE header indicates the type of file–GUI, CUI, or DLL—and also has a timestamp indicating when the file was built. For modules that contain only IL code (see below, Intermediate Language Code), the bulk of the information in the PE header is ignored. For modules that contain native CPU code, this header contains information about the native CPU code.

    CLR header : This header contains the information (interpreted by the CLR and utilities) that makes this a managed module. It includes the version of the CLR required, some flags, the MethodDef metadata token of the managed module’s entry point method (Main method), and the location/size of the module’s metadata, resources, strong name, some flags, and other less interesting stuff.

    MetaData : Every managed module contains metadata tables, of which there are 2 main types: those that describe the types and members defined in your source code, and those that describe the types and members referenced by your source code.

     Intermediate Language (IL) Code : This is the code that was produced by the compiler as it compiled the source code. IL is later compiled by the CLR into native CPU instructions.

    Most compilers of the past produced code targeted to a specific CPU architecture, such as x86, IA64, Alpha, or PowerPC. All CLR-compliant compilers produce intermediate language (IL) code instead. IL code is sometimes referred to as managed code, because its lifetime and execution are managed by the CLR.

    In brief, metadata is simply a set of data tables that describe what is defined in the module, such as types and
    their members.The metadata is always embedded in the same EXE/DLL as the code, making it impossible to separate the two. Since the metadata and code are produced by the compiler at the same time and are bound into the resulting managed module, the metadata and the IL code it describes are never out of sync with one another.
    Metadata has many uses. Here are some of them:

    • Metadata removes the need for header and library files when compiling, because all the information about the referenced types/members is contained in one file along with the IL that implements those type/members. Compilers can read metadata directly from managed modules.
    • Visual Studio uses metadata to help you write code. Its IntelliSense feature parses metadata to tell you what methods a type offers and what parameters that method expects.
    • The CLR code verification process uses metadata to ensure that your code performs only “safe” operations. Verification is discussed shortly.
    • Metadata allows an object’s fields to be serialized into a memory block, remoted to another machine, and then deserialized, recreating the object and its state on the remote machine.
    • Metadata allows the garbage collector to track the lifetime of objects. For any object, the garbage collector can determine the type of the object, and from the metadata it knows which fields within that object refer to other objects.

    The CLR doesn’t actually work with modules; it works with assemblies. An assembly is an abstract concept, which can be difficult to grasp at first. First, an assembly is a logical grouping of one or more managed modules or resource files. Second, an assembly is the smallest unit of reuse, security, and versioning. Depending on the choices you make with your compilers or tools, you can produce a single-file assembly or you can produce a multi-file assembly.

    Loading the Common Language Runtime

    When you build an EXE assembly, the compiler/linker emits some special information into the resulting assembly’s PE File header and the file’s .text section. When the EXE file is invoked, this special information causes the CLR to load and initialize. Then the CLR locates the entry point method for the application and lets the application start executing. 

    How a managed EXE loads and initializes the CLR.

    When the compiler/linker creates an executable assembly, the following 6-byte x86 stub function is emitted into the .text section of the PE file: JMP _CorExeMain The _CorExeMain function is imported from the Microsoft MSCorEE.dll dynamic-link library, and therefore MSCorEE.dll is referenced in the import (.idata) section of the assembly file. (MSCorEE.dll stands for Microsoft Component Object Runtime Execution Engine.) When the managed EXE file is invoked, Windows treats it just like any normal (unmanaged) EXE file: the Windows loader loads the file and examines the .idata section to see that MSCorEE.dll should be loaded into the process’s address space. Then, the loader obtains the address of the _CorExeMain function inside MSCorEE.dll and fixes up the stub function’s JMP instruction in the managed EXE file. The primary thread for the process begins executing this x86 stub function, which immediately jumps to _CorExeMain in MSCorEE.dll. _CorExeMain initializes the CLR and then looks at the CLR header for the executable assembly to determine what managed entry point method should execute. The IL code for the method is then compiled into native CPU instructions, after which the CLR jumps to the native code (using the process’s primary thread). At this point, the managed application code is running.

    The situation is similar for a managed DLL. When building a managed DLL, the compiler/linker emits a similar 6-byte x86 stub function for a DLL assembly in the .text section of the PE file: JMP _CorDllMain .  The _CorDllMain function is also imported from the MSCorEE.dll, causing the .idata section for the DLL to reference MSCorEE.dll. When Windows loads the DLL, it  automatically loads MSCorEE.dll (if it isn’t already loaded), obtains the address of the _CorDllMain function, and fixes up the 6 byte x86 JMP stub in the managed DLL. The thread that called LoadLibrary to load the managed DLL then jumps to the x86 stub in the managed DLL assembly, which immediately jumps to the _CorDllMain in MSCorEE.dll. _CorDllMain initializes the CLR (if it hasn’t already been initialized for the process) and then returns so that the application can continue executing as normal.

    We have shipped several versions of .Net framework: 1.0, 1.1, and 2.0 is on the horizon. All of them are side by side, meaning, someone may be using 1.0 CLR, at the same time, someone else is using 1.1 CLR. In the same process, there can be only one CLR. Once CLR is loaded in the process, it cannot be unloaded.

    Side by Side Execution 

    We have shipped several versions of .Net framework: 1.0, 1.1, 2.0,3.0,3.5 and 4.0 is on the horizon. All of them are side by side, meaning, someone may be using 2.0 CLR, at the same time, someone else is using 4.0 CLR. In the same process, there can be only one CLR (4.0 has new feature : In-process side by side (Inproc SxS) is the ability to run multiple versions of the CLR in a single process.). Once CLR is loaded in the process, it cannot be unloaded.

    So which CLR will my app use?

    It depends on which .Net framework has installed, and which framework your app is built with.

    The real component to determine which CLR to load is mscoree.dll, residing  in %windir%system32. When you install .Net framework, it will replace mscoree.dll if the existing one is older then the one it carries, and it will leave it alone if the existing one is newer. So we always have the latest mscoree.dll in %windir%system32, even the corresponding .Net framework has been uninstalled. For this reason, mscoree.dll has to maintain very strict compatibility.

     Because we always have the latest mscoree.dll, the following discussion is based on what newest .Net framework you have ever installed.

     If only 1.0 is installed, then 1.0 CLR will always be used. 1.0 mscoree.dll is not side by side aware.

     If 1.1 is installed, then the CLR you built with will be loaded. If you built your app with 1.0, then 1.0 CLR will be loaded. If you built your app with 1.1, then 1.1 CLR will be loaded. If the required CLR is not available in your machine, mscoree.dll will bring up a dialog and quit. This is so that your app won’t run under a different CLR that you did not test.

     The thinking shifts in 2.0. In 2.0, mscoree.dll will try to use the CLR you built with first. If that CLR cannot be found, mscoree.dll will load 2.0 CLR to run your app. But if the CLR you built with is newer than (the currently installed) 2.0, mscoree.dll will bring up the same dialog and quit. The latter behavior is frequently seen in internal testing.

     For apps built with interim release, mscoree.dll maps it to the closest officially released CLR. So 1.0 beta2+ will use 1.0 CLR. 1.1 beta will use 1.1 CLR.

     Of course, you can use a config file to overwrite the default behavior.

    Microsoft has released CLR (2.0) source code Implementation of CLI (Common Language Infrastructure) – ECMA standard that describes the core of the .NET Framework world.The Shared Source CLI goes beyond the printed specification of the ECMA standards, providing a working implementation for CLI developers to explore and understand.

    Developers interested in the internal workings of the .NET Framework can explore this implementation of the CLI to see how garbage collection works, JIT compilation and verification is handled, security protocols implemented, and the organization of frameworks and virtual object systems.

    Jump to Next Part : .Net CLR Internals (CLR modules in detail..)