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 Figure 3.
With each iteration of the loop, a Point value type is initialized. Then, the Point is stored in the ArrayList. But let's think about this for a moment. What is actually being stored in the ArrayList? Is it the Point structure, the address of the Point structure, or something else entirely? To get the answer, you must look up the ArrayList's Add method and see what type its parameter is defined as. In this case, you see that the Add method is prototyped in the following manner:
public virtual void Add(Object value)
The previous code plainly shows that Add takes an Object as a parameter. Object always identifies a reference type. But here I'm passing p, which is a Point value type. For this code to work, the Point value type must be converted into a true heap-managed object, and a reference to this object must be obtained.
Converting a value type to a reference type is called boxing. Internally, here's what happens when a value type is boxed:
Memory is allocated from the heap. The amount of memory allocated is the size required by the value type plus any additional overhead to consider this value a true object. The additional overhead includes a pointer to a virtual method table and a pointer to a sync block.
The value type's bits are copied to the newly allocated heap memory.
The address of the object is returned. This address is now a reference type.
Some language compilers, like C#, automatically produce the IL code necessary to box the value type, but it is important that you understand what's going on under the covers so that you are aware of code size and performance issues.
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);
In the two calls to WriteLine, the variable v (an Int32 unboxed value type) is passed by value. Now, it may be that WriteLine will box this Int32 internally, but you have no control over that. The important thing is that you've done the best you could and have eliminated the boxing from your code.
If you know that the code you're writing is going to cause the compiler to generate a lot of boxing code, you will get smaller and faster code if you manually box value types, as shown in Figure 4.
The C# compiler automatically generates boxing and unboxing code. This makes programming easier, but it hides the overhead from the programmer who is concerned with performance. Like C#, other languages may also hide boxing or unboxing details. However, some languages may force the programmer to explicitly write boxing or unboxing code. For example, C++ with Managed Extensions requires that the programmer explicitly box value types using the __box operator; unboxing a value type is done by casting the boxed type to its unboxed equivalent using dynamic_cast.
One last note: if a value type doesn't override a virtual method defined by System.ValueType, then this method can only be called on the boxed form of the value type. This is because only the boxed form of the object has a pointer to a virtual method table. Methods defined directly with the value type can be called on boxed and unboxed versions of the value.
Tuesday, April 26, 2005
Casting Continues....(Test ur Casting Skiils!!)
To make sure you understand everything presented in previous article, assume that the following two class definitions exist.
class B {
int x;
}
class D : B {
int x;
}
ES: Execute Successfully
CE: Compiler Error
RE: Runtime Error
Statement ES CE RE
System.Object o1 = new System.Object(); Y N N
System.Object o2 = new B(); Y N N
System.Object o3 = new D(); Y N N
System.Object o4 = o3; Y N N
B b1 = new B(); Y N N
B b2 = new D(); Y N N
D d1 = new D(); Y N N
B b3 = new System.Object(); N Y N
D d3 = new System.Object(); N Y N
B b3 = d1; Y N N
D d2 = b2; N Y N
D d4 = (D) d1; Y N N
D d5 = (D) b2; Y N N
D d6 = (D) b1; N N Y
B b4 = (B) o1; N N Y
B b5 = (D) b2; Y N N
class B {
int x;
}
class D : B {
int x;
}
ES: Execute Successfully
CE: Compiler Error
RE: Runtime Error
Statement ES CE RE
System.Object o1 = new System.Object(); Y N N
System.Object o2 = new B(); Y N N
System.Object o3 = new D(); Y N N
System.Object o4 = o3; Y N N
B b1 = new B(); Y N N
B b2 = new D(); Y N N
D d1 = new D(); Y N N
B b3 = new System.Object(); N Y N
D d3 = new System.Object(); N Y N
B b3 = d1; Y N N
D d2 = b2; N Y N
D d4 = (D) d1; Y N N
D d5 = (D) b2; Y N N
D d6 = (D) b1; N N Y
B b4 = (B) o1; N N Y
B b5 = (D) b2; Y N N
Monday, April 25, 2005
Implicit Casting / Explicit Casting / "as" Operator / "is" Operator
Let see them in action :
1. Implicit Casting
When programming, it is quite common to cast an object from one data type to another. In this section, I'll look at the rules that govern how objects are cast between data types. To start, look at the following line:
System.Object o = new Jeff("ConstructorParam1");
The previous line of code compiles and executes correctly because there is an implied cast. The new operator returns a reference to a Jeff type, but o is a reference to a System.Object type. Since all types (including the Jeff type) can be cast to System.Object, the implied cast is successful.
2. Explicit Casting
However, if you execute the following line, you get a compiler error since the compiler does not provide an implicit cast from a base type to a derived type.
Jeff j = o;
To get the command to compile, you must insert an explicit cast, as follows:
Jeff j = (Jeff) o;
Now the code compiles and executes successfully.
Let's look at another example:
System.Object o = new System.Object();
Jeff j = (Jeff) o;
On the first line, I have created an object of type System.Object. On the second line, I am attempting to convert a reference of type System.Object to a reference of type Jeff. Both lines of code compile just fine. However, when executed, the second line generates an InvalidCastException exception, which if not caught, forces the application to terminate.
When the second line of code executes, the common language runtime verifies that the object referred to by o is in fact an object of type Jeff (or any type derived from type Jeff). If so, the common language runtime allows the cast. However, if the object referenced by o has no relationship to Jeff, or is a base class of Jeff, then the common language runtime prevents the unsafe cast and raises the InvalidCastException exception.
3. as Operator
C# offers another way to perform a cast using the as operator:
Jeff j = new Jeff(); // Create a new Jeff object
System.Object o = j as System.Object; // Casts j to an object
// o now refers to the Jeff object
The as operator attempts to cast an object to the specified type. However, unlike normal casting, the as operator will never throw an exception. Instead, if the object's type cannot be cast successfully, then the result is null. When the ill-cast reference is used, a NullReferenceException exception will be thrown. The following code demonstrates this concept.
System.Object o = new System.Object(); //Creates a new Object object
Jeff j = o as Jeff; //Casts o to a Jeff
// The cast above fails: no exception is raised but j is set to null
j.ToString(); // Accessing j generates a NullReferenceException
Here comes the Final Rescue !!
4. is Operator
In addition to the as operator, C# also offers an is operator. The is operator checks whether an object instance is compatible with a given type and the result of the evaluation is either True or False. The is operator will never raise an exception.
System.Object o = new System.Object();
System.Boolean b1 = (o is System.Object); // b1 is True
System.Boolean b2 = (o is Jeff); // b2 is False
Note, if the object reference is null, the is operator always returns False since there is no object available to check its type.
That's all i can say ...Happy Casting !!
Regards,
Deepak
1. Implicit Casting
When programming, it is quite common to cast an object from one data type to another. In this section, I'll look at the rules that govern how objects are cast between data types. To start, look at the following line:
System.Object o = new Jeff("ConstructorParam1");
The previous line of code compiles and executes correctly because there is an implied cast. The new operator returns a reference to a Jeff type, but o is a reference to a System.Object type. Since all types (including the Jeff type) can be cast to System.Object, the implied cast is successful.
2. Explicit Casting
However, if you execute the following line, you get a compiler error since the compiler does not provide an implicit cast from a base type to a derived type.
Jeff j = o;
To get the command to compile, you must insert an explicit cast, as follows:
Jeff j = (Jeff) o;
Now the code compiles and executes successfully.
Let's look at another example:
System.Object o = new System.Object();
Jeff j = (Jeff) o;
On the first line, I have created an object of type System.Object. On the second line, I am attempting to convert a reference of type System.Object to a reference of type Jeff. Both lines of code compile just fine. However, when executed, the second line generates an InvalidCastException exception, which if not caught, forces the application to terminate.
When the second line of code executes, the common language runtime verifies that the object referred to by o is in fact an object of type Jeff (or any type derived from type Jeff). If so, the common language runtime allows the cast. However, if the object referenced by o has no relationship to Jeff, or is a base class of Jeff, then the common language runtime prevents the unsafe cast and raises the InvalidCastException exception.
3. as Operator
C# offers another way to perform a cast using the as operator:
Jeff j = new Jeff(); // Create a new Jeff object
System.Object o = j as System.Object; // Casts j to an object
// o now refers to the Jeff object
The as operator attempts to cast an object to the specified type. However, unlike normal casting, the as operator will never throw an exception. Instead, if the object's type cannot be cast successfully, then the result is null. When the ill-cast reference is used, a NullReferenceException exception will be thrown. The following code demonstrates this concept.
System.Object o = new System.Object(); //Creates a new Object object
Jeff j = o as Jeff; //Casts o to a Jeff
// The cast above fails: no exception is raised but j is set to null
j.ToString(); // Accessing j generates a NullReferenceException
Here comes the Final Rescue !!
4. is Operator
In addition to the as operator, C# also offers an is operator. The is operator checks whether an object instance is compatible with a given type and the result of the evaluation is either True or False. The is operator will never raise an exception.
System.Object o = new System.Object();
System.Boolean b1 = (o is System.Object); // b1 is True
System.Boolean b2 = (o is Jeff); // b2 is False
Note, if the object reference is null, the is operator always returns False since there is no object available to check its type.
That's all i can say ...Happy Casting !!
Regards,
Deepak
Garbage Collection in .NET + Weak References
Best article on Gabage Collection i have ever seen on the earth !!
Apart from Garbage collection it also tell u about Weak References...
Weak references are a means of performance enhancement, used to reduce the pressure placed on the managed heap by large objects.
When a root points to an abject it's called a strong reference to the object and the object cannot be collected because the application's code can reach the object.
When an object has a weak reference to it, it basically means that if there is a memory requirement & the garbage collector runs, the object can be 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 GC cannot collect the object because a strong reference to the object exists.
http://www.codeproject.com/dotnet/garbagecollection.asp
To support this article, we have another article by our Windows Guru Jeffery Richter
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx
Sample Code for 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
}
Bye for Now..Will come again !!
Apart from Garbage collection it also tell u about Weak References...
Weak references are a means of performance enhancement, used to reduce the pressure placed on the managed heap by large objects.
When a root points to an abject it's called a strong reference to the object and the object cannot be collected because the application's code can reach the object.
When an object has a weak reference to it, it basically means that if there is a memory requirement & the garbage collector runs, the object can be 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 GC cannot collect the object because a strong reference to the object exists.
http://www.codeproject.com/dotnet/garbagecollection.asp
To support this article, we have another article by our Windows Guru Jeffery Richter
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx
Sample Code for 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
}
Bye for Now..Will come again !!
Thursday, April 14, 2005
.NET Questions Bank - Good Collection
http://groups.msn.com/MumbaiUserGroup/netinterviewquestions.msnw
Thursday, December 16, 2004
Tuesday, November 16, 2004
SQL DMO - Distributed Management Objects
Dim objsqlserver As New SQLDMO.SQLServer
Private Sub Command1_Click()
objsqlserver.LoginTimeout = 30
objsqlserver.Connect "SERVER_Name", "sa", "sa"
MsgBox "Connected!!"
End Sub
Private Sub Command2_Click()
Dim TestTable As SQLDMO.Table
Dim colAge As New SQLDMO.Column
colAge.Name = "Age"
colAge.Datatype = "char"
colAge.Length = 10
colAge.AllowNulls = True
Set TestTable = objsqlserver.Databases("DB_Name").Tables("Test_Table")
TestTable.BeginAlter
TestTable.Columns.Add colAge
TestTable.DoAlter
End Sub
Private Sub Command1_Click()
objsqlserver.LoginTimeout = 30
objsqlserver.Connect "SERVER_Name", "sa", "sa"
MsgBox "Connected!!"
End Sub
Private Sub Command2_Click()
Dim TestTable As SQLDMO.Table
Dim colAge As New SQLDMO.Column
colAge.Name = "Age"
colAge.Datatype = "char"
colAge.Length = 10
colAge.AllowNulls = True
Set TestTable = objsqlserver.Databases("DB_Name").Tables("Test_Table")
TestTable.BeginAlter
TestTable.Columns.Add colAge
TestTable.DoAlter
End Sub
Thursday, September 23, 2004
Thursday, September 16, 2004
Wednesday, September 15, 2004
Web Forms DataGrid and DataSet Programming
http://www.developerfusion.com/scripts/print.aspx?id=3801
DataGrid,Data List and Repeater - Which to Use When...Good Question
Fundu artcle by scott Michel (ASP.NET Guru...I m saluting to this guy....)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/aspnet-whenusedatawebcontrols.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/aspnet-whenusedatawebcontrols.asp
Wednesday, August 25, 2004
Crystal Report.NET......Alag Duniya!!
Useful Links..
1. Regarding Deployment
http://support.businessobjects.com/communityCS/TechnicalPapers/crnet_deployment.pdf
2. Regarding Licence
http://www.businessobjects.com/products/reporting/crystalreports/net/licensing.asp
3. General Stuff - Reporting Decisions in .NET!!
http://www.c-sharpcorner.com/Code/2004/Feb/ReportsInDotNet.asp
1. Regarding Deployment
http://support.businessobjects.com/communityCS/TechnicalPapers/crnet_deployment.pdf
2. Regarding Licence
http://www.businessobjects.com/products/reporting/crystalreports/net/licensing.asp
3. General Stuff - Reporting Decisions in .NET!!
http://www.c-sharpcorner.com/Code/2004/Feb/ReportsInDotNet.asp
Tuesday, August 24, 2004
Thursday, August 12, 2004
Value Types Vs reference Types
Introduction:
There are basically two types of variables in Common Type System ?
1) Value Type: Get Stored on Stack Memory.
2) Reference Type: Get Stored on Managed Heap Memory
How this Works?
Value types get stored on stack and shared the same process memory, however the Reference Types get stored on Heap and their memory address value gets stored on the stack as value type.
Question: When an object (child Object) is instantiated inside an object (parent Object) where does it get stored?
Answer: The value of child object (Reference type) gets stored in another random memory area on the managed heap and its reference (memory address value) gets stored in the managed heap of the Parent Object as Value Type.
The value of child object (Value type) gets stored in the Parent object's memory area of the managed heap.
For Example:
Module Module1 'Main Entry
Sub Main()
Dim i As Integer = 50
Dim objA As classA = New ClassA
Dim j As Integer = 25
End Sub
End Module
Public Class ClassA 'Parent Class
Dim obj As New ClassB
Dim MoreInfo As String = "sample"
End Class
Public Class ClassB 'Child Class
Public name As String
Public age As Integer
End Class
Value of the ObjA gets stored in the Managed Heap and its memory address value gets stored on the Stack. But, in case of ObjB the value of the ObjB gets stored at another location in the Managed Heap and the memory address value of this location gets stored as a value type in ObjA Managed Heap.
There are basically two types of variables in Common Type System ?
1) Value Type: Get Stored on Stack Memory.
2) Reference Type: Get Stored on Managed Heap Memory
How this Works?
Value types get stored on stack and shared the same process memory, however the Reference Types get stored on Heap and their memory address value gets stored on the stack as value type.
Question: When an object (child Object) is instantiated inside an object (parent Object) where does it get stored?
Answer: The value of child object (Reference type) gets stored in another random memory area on the managed heap and its reference (memory address value) gets stored in the managed heap of the Parent Object as Value Type.
The value of child object (Value type) gets stored in the Parent object's memory area of the managed heap.
For Example:
Module Module1 'Main Entry
Sub Main()
Dim i As Integer = 50
Dim objA As classA = New ClassA
Dim j As Integer = 25
End Sub
End Module
Public Class ClassA 'Parent Class
Dim obj As New ClassB
Dim MoreInfo As String = "sample"
End Class
Public Class ClassB 'Child Class
Public name As String
Public age As Integer
End Class
Value of the ObjA gets stored in the Managed Heap and its memory address value gets stored on the Stack. But, in case of ObjB the value of the ObjB gets stored at another location in the Managed Heap and the memory address value of this location gets stored as a value type in ObjA Managed Heap.
Monday, August 09, 2004
Good Article/Funda of CLR Internal
Here goes the very good article from MSDN India:
Its good for basic understanding........
Ever wondered what happens behind the scenes when we click a managed executable (.EXE). Yes, the application starts, but how does it starts and what all happens behind the scene. Here we will talk, what all happens when a managed application is launched. But before that we’ll go through a basic overview of CLR Hosting!
CLR Hosting defines how the CLR is loaded into the process, the transition from unmanaged environment to managed environment and execution of applications. There is a Runtime Host, an unmanaged code shim, which loads the CLR into the process. This runtime host first creates an Application Domain called “Default Application Domain” where the runtime is loaded. Then the control is transferred to this managed runtime and it further creates more application domains, load managed user code and executes them without using any unmanaged code. This execution of user code into the managed environment without any calls going to unmanaged environment gives us a performance increase because making calls from managed to unmanaged is expensive. Another feature of Hosting is that it provides some unmanaged APIs also with which we can write our custom runtime host specifically designed for our application.
Now we will explain the process which happens behind the scene before the application starts. When a managed EXE is clicked, first the CLR is loaded into the process. When the runtime is loaded, then the control is passed from unmanaged code to manage code. This managed code further creates application domain and loads the user code into these application domains. CLR then checks the user code for verification, type safety, security checks, etc. After it finishes, the Class Loader finds the class (the entry point) inside the assembly, loads it and loads other classes which are directly called from the entry point method. JIT compiles this managed code to native CPU instruction set and let the processor executes these instruction sets. JIT does not compile all the managed code into the native code at once. It does it on demand basis. Means during the execution time of the user code, if the runtime engine needs to use the code of another assembly or same assembly, it converts into native code at that time, not during the first JIT. Let see this process in detail.
Loading the runtime into the process
Before any managed code is executed, the runtime must be loaded into the process and initialize the common language runtime. This loading of runtime into the process is to be done by an unmanaged code because for executing a managed code, we still need the runtime into the process and this is what we want to do. So we have an unmanaged code stub from where we start. This unmanaged code stub is in the “mscoree.dll” file placed in “%windir%/system32”. .NET Framework provides a set of unmanaged APIs called “Hosting APIs” which helps us in loading the runtime. An unmanaged method, CorBindToRuntimeEx, is called for hosting the runtime into the process. This method have few parameters which defines which version of runtime is to be loaded, which runtime build to load (server or workstation), which garbage collection technique to be used (concurrent or non-concurrent) and other details. Also this unmanaged code stub creates a default application domain where the runtime is to be loaded because in .NET Framework, managed code is loaded into application domains (logical process which restrict the application boundary) and executed there hence required.
Transition from unmanaged code to managed code
Once the default application domain is created, there is a need to transfer the control from the unmanaged code to managed code. There are few reasons for that. Firstly, if we don’t transfer the control, then the user code would be loaded in a managed environment and any call originating from the user code need to cross the managed environment to the unmanaged environment and this is expensive. There will be a performance hit in this case. Moreover if the user code is managed by runtime in the managed environment only, it provide more security and easily manageable without any interoperability layer coming in between.
Once the default application domain is created, the runtime host gets a pointer to that default domain and loads the runtime into that default domain. To get the pointer to the default domain, we have an interface called ICorRuntimeHost which enables the host to accomplish task like configuration setting, getting default domain, etc. Once the host gets the pointer of the default domain it loads the managed portion of runtime into the default application domain. When the transition is complete, the unmanaged stub is no longer required as our runtime manages everything from this point.
Runtime create App Domains and loads the user code
To load the user code and execute it, there should be more application domains beside the “default application domain”. In “Default application domain” only hosts the runtime and domain-neutral assemblies can reside. For user code, the runtime have to create more application domains specific to the application. The runtime decides where the application domain is to be created depending on the application memory requirement and isolation factor. Again the runtime sets the user application domain configuration settings like setting the root directory from where the application domain will be looking for private assemblies. Isolation is an important factor because if the applications are not isolated properly, then breakdown of one application may lead to breakdown of other application sharing the application domain. When the application domain is created and its configuration is set, the managed user code (Assembly) is loaded in the application domain. Here managed user code means any code that is not part of the host. The user code is loaded into the application domain using System.Appdomain.Load () method which is overloaded with various inputs or emitting a dynamic assembly using System.Reflection.Emit namespace.
Runtime verifies the assembly loaded; checks for type safety, security
Any user code which is loaded into the application domain has to pass the verification test done by runtime unless it is configured to be bypassed by the administrator. In verification, the runtime checks the MSIL and Metadata to find out whether the code can marked as type safe which means that every object in the code refers to a known and authorized memory location. It also checks if the referencing object is strictly compatible with the object that is being referenced to. These are the basic checks that are done by runtime for type safety. Also security checks are done here. It checks if the caller has the permission to execute this code. All security checks are done for every method in the assembly.
Class Loader loads the classes from the assembly
The loader reads the metadata and code modules, identifies the “entry point” (method that is executed when the code is first run). This incorporates a complex process of loading a class from a physical file from hard disk/network, from a dynamic assembly which is in the memory, caching the Type information, performing some JIT and garbage collection housekeeping, and then passing control to the JIT compilers. This loader basically figures out the number and type of fields so that runtime can create instances for the same. It also has to check the classes it is loading, does it have any relationship with other classes like is it a derived class or a parent class because some of the member might be overridden from the base class in child class. Then these classes are forwarded to JIT to native compilation. The loader doesn’t forward all the code to JIT. When the method is needed, only then it is given to JIT for compilation. So the method which are not called directly from the entry points, there stubs are created and when these methods are called, these stubs passes the control to JIT.
JIT compiles the MSIL to native managed code
JIT a synonym for “Just In Time” Compiler converts the MSIL to native CPU instruction set. The instruction set to which the MSIL is converted is specific to the CPU where the code is being executed. This helps in using the extended instruction set specific to that CPU Architecture and model. JIT compilation thinks that some code would never be executed so it just compiles the necessary code to start into native code. Rest all the code is compiled on demand basis, means as and when the method needs to be executed; the stub attached to the method passes the control to JIT to compile the MSIL code. Once the MSIL code is converted to native code, it need not convert it again and again on subsequent calls. This native code is cached and used for subsequent calls.
Now the MSIL is converted into native code, the application starts and we see our User Interface for the application; may it be Web application or Windows based Application. I have tried to give you an idea what all happens behind the scene including the CLR internals as to how it works.
Maja aaya ya Nahi....????? I hope u Njoyed it...
Its good for basic understanding........
Ever wondered what happens behind the scenes when we click a managed executable (.EXE). Yes, the application starts, but how does it starts and what all happens behind the scene. Here we will talk, what all happens when a managed application is launched. But before that we’ll go through a basic overview of CLR Hosting!
CLR Hosting defines how the CLR is loaded into the process, the transition from unmanaged environment to managed environment and execution of applications. There is a Runtime Host, an unmanaged code shim, which loads the CLR into the process. This runtime host first creates an Application Domain called “Default Application Domain” where the runtime is loaded. Then the control is transferred to this managed runtime and it further creates more application domains, load managed user code and executes them without using any unmanaged code. This execution of user code into the managed environment without any calls going to unmanaged environment gives us a performance increase because making calls from managed to unmanaged is expensive. Another feature of Hosting is that it provides some unmanaged APIs also with which we can write our custom runtime host specifically designed for our application.
Now we will explain the process which happens behind the scene before the application starts. When a managed EXE is clicked, first the CLR is loaded into the process. When the runtime is loaded, then the control is passed from unmanaged code to manage code. This managed code further creates application domain and loads the user code into these application domains. CLR then checks the user code for verification, type safety, security checks, etc. After it finishes, the Class Loader finds the class (the entry point) inside the assembly, loads it and loads other classes which are directly called from the entry point method. JIT compiles this managed code to native CPU instruction set and let the processor executes these instruction sets. JIT does not compile all the managed code into the native code at once. It does it on demand basis. Means during the execution time of the user code, if the runtime engine needs to use the code of another assembly or same assembly, it converts into native code at that time, not during the first JIT. Let see this process in detail.
Loading the runtime into the process
Before any managed code is executed, the runtime must be loaded into the process and initialize the common language runtime. This loading of runtime into the process is to be done by an unmanaged code because for executing a managed code, we still need the runtime into the process and this is what we want to do. So we have an unmanaged code stub from where we start. This unmanaged code stub is in the “mscoree.dll” file placed in “%windir%/system32”. .NET Framework provides a set of unmanaged APIs called “Hosting APIs” which helps us in loading the runtime. An unmanaged method, CorBindToRuntimeEx, is called for hosting the runtime into the process. This method have few parameters which defines which version of runtime is to be loaded, which runtime build to load (server or workstation), which garbage collection technique to be used (concurrent or non-concurrent) and other details. Also this unmanaged code stub creates a default application domain where the runtime is to be loaded because in .NET Framework, managed code is loaded into application domains (logical process which restrict the application boundary) and executed there hence required.
Transition from unmanaged code to managed code
Once the default application domain is created, there is a need to transfer the control from the unmanaged code to managed code. There are few reasons for that. Firstly, if we don’t transfer the control, then the user code would be loaded in a managed environment and any call originating from the user code need to cross the managed environment to the unmanaged environment and this is expensive. There will be a performance hit in this case. Moreover if the user code is managed by runtime in the managed environment only, it provide more security and easily manageable without any interoperability layer coming in between.
Once the default application domain is created, the runtime host gets a pointer to that default domain and loads the runtime into that default domain. To get the pointer to the default domain, we have an interface called ICorRuntimeHost which enables the host to accomplish task like configuration setting, getting default domain, etc. Once the host gets the pointer of the default domain it loads the managed portion of runtime into the default application domain. When the transition is complete, the unmanaged stub is no longer required as our runtime manages everything from this point.
Runtime create App Domains and loads the user code
To load the user code and execute it, there should be more application domains beside the “default application domain”. In “Default application domain” only hosts the runtime and domain-neutral assemblies can reside. For user code, the runtime have to create more application domains specific to the application. The runtime decides where the application domain is to be created depending on the application memory requirement and isolation factor. Again the runtime sets the user application domain configuration settings like setting the root directory from where the application domain will be looking for private assemblies. Isolation is an important factor because if the applications are not isolated properly, then breakdown of one application may lead to breakdown of other application sharing the application domain. When the application domain is created and its configuration is set, the managed user code (Assembly) is loaded in the application domain. Here managed user code means any code that is not part of the host. The user code is loaded into the application domain using System.Appdomain.Load () method which is overloaded with various inputs or emitting a dynamic assembly using System.Reflection.Emit namespace.
Runtime verifies the assembly loaded; checks for type safety, security
Any user code which is loaded into the application domain has to pass the verification test done by runtime unless it is configured to be bypassed by the administrator. In verification, the runtime checks the MSIL and Metadata to find out whether the code can marked as type safe which means that every object in the code refers to a known and authorized memory location. It also checks if the referencing object is strictly compatible with the object that is being referenced to. These are the basic checks that are done by runtime for type safety. Also security checks are done here. It checks if the caller has the permission to execute this code. All security checks are done for every method in the assembly.
Class Loader loads the classes from the assembly
The loader reads the metadata and code modules, identifies the “entry point” (method that is executed when the code is first run). This incorporates a complex process of loading a class from a physical file from hard disk/network, from a dynamic assembly which is in the memory, caching the Type information, performing some JIT and garbage collection housekeeping, and then passing control to the JIT compilers. This loader basically figures out the number and type of fields so that runtime can create instances for the same. It also has to check the classes it is loading, does it have any relationship with other classes like is it a derived class or a parent class because some of the member might be overridden from the base class in child class. Then these classes are forwarded to JIT to native compilation. The loader doesn’t forward all the code to JIT. When the method is needed, only then it is given to JIT for compilation. So the method which are not called directly from the entry points, there stubs are created and when these methods are called, these stubs passes the control to JIT.
JIT compiles the MSIL to native managed code
JIT a synonym for “Just In Time” Compiler converts the MSIL to native CPU instruction set. The instruction set to which the MSIL is converted is specific to the CPU where the code is being executed. This helps in using the extended instruction set specific to that CPU Architecture and model. JIT compilation thinks that some code would never be executed so it just compiles the necessary code to start into native code. Rest all the code is compiled on demand basis, means as and when the method needs to be executed; the stub attached to the method passes the control to JIT to compile the MSIL code. Once the MSIL code is converted to native code, it need not convert it again and again on subsequent calls. This native code is cached and used for subsequent calls.
Now the MSIL is converted into native code, the application starts and we see our User Interface for the application; may it be Web application or Windows based Application. I have tried to give you an idea what all happens behind the scene including the CLR internals as to how it works.
Maja aaya ya Nahi....????? I hope u Njoyed it...
Wednesday, July 28, 2004
.NET Developer's Guide to Windows Security
Hi,
This is really good book for Security......Now a days I m in love with it.......
A .NET Developer's Guide to Windows Security, by Keith Brown
http://www.pluralsight.com/keith/book/html/book.html
This is really good book for Security......Now a days I m in love with it.......
A .NET Developer's Guide to Windows Security, by Keith Brown
http://www.pluralsight.com/keith/book/html/book.html
Fundoooooooooooooooooooo......Maja aa gaya......!!!!
Tuesday, July 13, 2004
Funda No.2: What are Static/Type Constructors? Good Question!!
Even I came to know about it Today!!!
Static/Type Constructors
You are already familiar with constructors, which are responsible for setting an object instance to its initial state. In addition to instance constructors, the Microsoft® .NET common language runtime (CLR) also supports type constructors (also known as static constructors, class constructors, or type initializers). A type constructor can be applied to interfaces, classes, and value types. It allows the type to perform any initialization required before any members declared within the type are accessed. Type constructors accept no parameters and always have a return type of void. A type constructor only has access to a type's static fields and its usual purpose is to initialize those fields. A type's constructor is guaranteed to run before any instance of the type is created and before any static field or method of the type is referenced.
Many languages (including C#) automatically generate type constructors for any types you define. However, some languages will require you to implement the type constructors explicitly.
To understand type constructors, examine the following type (defined in C#):
class AType {
static int x = 5;
}
When this code is built, the compiler automatically generates a type constructor for AType. This constructor is responsible for initializing the static field x to the value 5. If you're using ILDasm, you can easily spot type constructor methods because they have a name of .cctor (for class constructor).
In C#, you can implement type constructors yourself by defining a static constructor method in your type. The use of the static keyword makes the constructor a type constructor rather than an instance constructor. Here is a very simple example:
class AType {
static int x;
static AType() {
x = 5;
}
}
This type definition is identical to the previous one. Note that a type constructor must never attempt to create any instances of its own type, and the constructor must not reference any of the type's nonstatic members.
Finally, if you give the C# compiler the following code, it generates a single type constructor method.
class AType {
static int x = 5;
static AType() {
x = 10;
}
}
This constructor first initializes x to 5 and then initializes x to 10. In other words, the resulting type constructor generated by the compiler first contains the static field initialization code, which is then followed by the code in your type constructor method.
Kyon Kaisee rahi.........
Bye Deepak.....Watch out for funda No.3............
Static/Type Constructors
You are already familiar with constructors, which are responsible for setting an object instance to its initial state. In addition to instance constructors, the Microsoft® .NET common language runtime (CLR) also supports type constructors (also known as static constructors, class constructors, or type initializers). A type constructor can be applied to interfaces, classes, and value types. It allows the type to perform any initialization required before any members declared within the type are accessed. Type constructors accept no parameters and always have a return type of void. A type constructor only has access to a type's static fields and its usual purpose is to initialize those fields. A type's constructor is guaranteed to run before any instance of the type is created and before any static field or method of the type is referenced.
Many languages (including C#) automatically generate type constructors for any types you define. However, some languages will require you to implement the type constructors explicitly.
To understand type constructors, examine the following type (defined in C#):
class AType {
static int x = 5;
}
When this code is built, the compiler automatically generates a type constructor for AType. This constructor is responsible for initializing the static field x to the value 5. If you're using ILDasm, you can easily spot type constructor methods because they have a name of .cctor (for class constructor).
In C#, you can implement type constructors yourself by defining a static constructor method in your type. The use of the static keyword makes the constructor a type constructor rather than an instance constructor. Here is a very simple example:
class AType {
static int x;
static AType() {
x = 5;
}
}
This type definition is identical to the previous one. Note that a type constructor must never attempt to create any instances of its own type, and the constructor must not reference any of the type's nonstatic members.
Finally, if you give the C# compiler the following code, it generates a single type constructor method.
class AType {
static int x = 5;
static AType() {
x = 10;
}
}
This constructor first initializes x to 5 and then initializes x to 10. In other words, the resulting type constructor generated by the compiler first contains the static field initialization code, which is then followed by the code in your type constructor method.
Kyon Kaisee rahi.........
Bye Deepak.....Watch out for funda No.3............
Funda No.1 : Sealed Modifier in C# - Really Good
Hi Guys,
Look into it.....
Funda No.1 :
In Beta 1, the Sealed modifier, when used on method overrides, yielded a compiler error: "The modifier 'sealed' is not valid for this item." In Beta 2, the compiler recognizes the Sealed modifier.
Sample Code Snippet:
public class B : A
{
public B()
{
}
sealed public override string Method1()
{
return "Override";
}
}
Use of the Sealed modifier, in conjunction with the override method, will prevent anything classes derive from class B from further overriding Method1(), which originally was provided by the base class A.
So Hows That....
Look into it.....
Funda No.1 :
In Beta 1, the Sealed modifier, when used on method overrides, yielded a compiler error: "The modifier 'sealed' is not valid for this item." In Beta 2, the compiler recognizes the Sealed modifier.
Sample Code Snippet:
public class B : A
{
public B()
{
}
sealed public override string Method1()
{
return "Override";
}
}
Use of the Sealed modifier, in conjunction with the override method, will prevent anything classes derive from class B from further overriding Method1(), which originally was provided by the base class A.
So Hows That....
Tuesday, June 15, 2004
Subscribe to:
Comments (Atom)