Welcome to AspAdvice Sign in | Join | Help

From .NET Geek's Desk

Thoughts and Findings on .NET
APTCA and Sandboxing

In .NET Framework any code which does not have the FullTrust cannot make calls to a strong named assembly.The strong naming of assemblies is again a requirement to register the same in GAC to be shared by multiple applications.Most of the third party libraries we use are strong named.Is there a way out by which an assembly can reside in the GAC and at the same time can be used by partially trusted code?

The answer is YES.For this we have got the AllowPartiallyTrustedCallers (APTCA)attribute.The strong named assemblies that apply this attribute can be invoked by partially trusted code.This however, increases the overall vulnerability of the application.Library publishers as well the client application developers needs to consider the possible threats related to APTCA before using it.When an assembly is marked with the APTCA attribute then the LinkDemand requiring all the callers to be full trusted is disabled.But there can be scenario where I would like some types/methods in the assembly to be accessed by partially trusted callers and some to be accessed only by callers with FullTrust.This can be achieved by

  • Applying APTCA to the assembly
    • [assembly:AllowPartiallyTrustedCallersAttribute()]
  • Apply LinkDemand for FullTrust on particular types/methods
    • [PermissionSetAttribute(SecurityAction.LinkDemand, Name="FullTrust")]

Now think of a situation where you have been supplied with a third party assembly which does not have APTCA.You are asked to use it from your ASP.NET Web Application running with medium trust policy (though by default ASP.NET applications have FullTrust).What happens now?I tried to simulate the situation with strong named assembly "DummyThirdPartyLib.dll" without APTCA with a demo method as shown below:

namespace DummyThirdPartyLib
{
    public class Test
    {
        public string HelloWorld()
        {
            return "Hello World";
        }
    }
}

I Changed the trust level of the web application to Medium by following setting in Web.config

<trust level="Medium"/>

In the page load I added a call to the assembly:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(new Test().HelloWorld());
    }
}

I got the following error:

System.Security.SecurityException: That assembly does not allow partially trusted callers.

As per our understanding of APTCA this is what is expected.So we need a work around to tackle this situation as we cannot request the publishers of third party library to change their code.We can solve this very easily by sandboxing the third party assembly.This is achieved by

  • Develop a wrapper assembly around the third party assembly.
  • Mark the wrapper assembly with APTCA
  • Put the wrapper assembly in GAC so that it has FullTrust

I followed the steps mentioned above.Developed a wrapper assembly with APTCA and placed it in GAC as shown below:

namespace APTCAWrapper {

    public class Wrapper {

        public string HelloWorld()
        {

            return new DummyThirdPartyLib.Test().HelloWorld();
        }
    }
}

Changed the call in Page Load as follows:

protected void Page_Load(object sender, EventArgs e)
{
    Response.Write(new APTCAWrapper.Wrapper().HelloWorld());
}

My code executes and displays Hello World.Great!!!.This will be particularly very helpful while working with third party libraries from MOSS which by default runs with Medium Trust.

Sponsor
.NET Memory Management and GCHandle

GC Handle provides facilities to explicitly control and monitor the lifetime of an object in heap.Whenever an appdomain loads it creates a GC Handle table which maintains a list of pointers and corresponding GC Handle type.The GC Handle can be obtained using the structure System.Runtime.InteropServices.GCHandle and System.Runtime.InteropServices.GCHandleType enumeration.The GCHandleType can have the following values:

  • Weak
    • This type of GC Handle allow the object to be collected.When the object is collected the GCHandle is zeroed even if the finalizer resurrect the reference.
  • WeakTrackResurrection
    • This is similar to Weak apart from the fact that it is not zeroed if the object is resurrected during finalization.
  • Normal
    • This GC Handle prevents the object from being collected.
  • Pinned
    • This GC Handle prevents the object from being collected as well moved during heap compaction.

The GCHandle is obtained using the GCHandle.Alloc method and it is freed using the GCHandle.Free() method as shown in the code sample below:

byte[] buffer = new byte[1024];
GCHandle hnd = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = hnd.AddrOfPinnedObject();
//Call unmanged code.....

if (hnd.IsAllocated) hnd.Free();

If you are using a Normal GCHandle then AddrOfPinnedObject cannot be used.The pointer can be obtained using

(IntPtr)hnd

The GCHandleType Pinned is particularly used for passing reference between managed and unmanaged code during the P/Invoke calls.But pinning has impact on the performance of the garbage collector.So it is very important to have a clear idea on when to pin the object.In most of the CLR P/Invoke layer automatically pins an object before the call and unpins it after the call returns.This is much more efficient than explicit pinning using GCHandle.But there can be situation when we need to keep the object fixed in memory even after the unmanaged function returns.This is very much true in case of an asynchronous unmanaged call involving I/O operation.For example if I am making an unmanaged function which takes a file handle and buffer as input and asynchronously reads the file and populates the buffer then it is absolutely necessary to keep the buffer fixed in memory. 

This is explained in Chris Brummes Blog very crisply.

http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx

The PnP Interop Performance Guidelines also clearly suggests to Avoid Aggressive Pinning of Short-Lived Objects

Sponsor
Physical Layout of Data - StructLayout

This week I was taking a close look into various InterOp related stuff for a code review purpose.While doing so the way CLR controls the physical layout of a data structure in memory caught my attention.This is what I intend to discuss here.

When we are declaring a set of fields for a structure or class the ordering of variables in the code has no impact on the physical ordering of the variables in memory(unmanaged memory) unless we are instructing the CLR specifically to do so.This can be done by applying the System.Runtime.InteropServices.StructLayoutAttribute attribute on the class or structure.This attribute accepts a value from enumeration System.Runtime.InteropServices.LayoutKind as constructor.This enumeration has 3 values:

  1. Auto - Runtime automatically decides about the layout of the data structure.
  2. Sequential - The fields are layout sequentially in the memory.This is determined by pack size specified by System.Runtime.InteropServices.StructLayoutAttribute.PackSize property.This layout can be non contiguous as well.
  3. Explicit - The position of each member is explicitly controlled by specifying the System.Runtime.InteropServices.FieldOffsetAttribute class.This attribute is applied at field level and accepts the offset in bytes as constructor as shown below:

[StructLayout(LayoutKind.Explicit)]
  public class TestObject
  {
      [FieldOffset(0)] 
      public Int32 i;
      [FieldOffset(8)]
      public Int32 j;
      [FieldOffset(4)]
      public Int32 k;
  }

Now to test whether offset is truly taking effect I wrote few lines of unsafe code as shown below:

static void Main(string[] args)
{
           TestObject t = new TestObject();
           t.i = 10;
           t.j = 20;
           t.k = 30;

           unsafe
           {
               fixed (int* p = &t.i)
               {
                   //i has first position
                   Console.WriteLine("Value Of i is " + *p);
                   //j has third position
                   Console.WriteLine("Value Of j is " + *(p+2));
                   //k has second position
                   Console.WriteLine("Value Of k is " + *(p+1));
               }
           }

}

And the program prints the values correctly meaning this works well.WoW!!!

Sponsor
Functional Construction in LINQ To XML

In this post we describe how we can create XML documents using LINQ to XML.Here we will discuss about functional construction of a XML tree in which we can construct a XML document using a single statement.Before getting into examples let us take a look at the constructors of System.Xml.XLinq.XAttribute class.

public XElement(XName name,Object content) - This constructor takes the name of the element and a content object which can be another XElement or XAttribute as shown below:

 XElement po = new XElement("PurchaseOrders",
                                        new XElement("PurchaseOrder"
                                            )
                                        );

Console.WriteLine(po);

Here we are creating a simple document with PurchaseOrder element as child of PurchaseOrders as shown below:

<PurchaseOrders>
  <PurchaseOrder />
</PurchaseOrders>

public XElement(XName name,Object[] content) - This constructor is quite similar to the first apart from the fact that it accepts an array of XElement or XAttribute as the content object as shown below:

XElement po = new XElement("PurchaseOrders",
                            new XElement("PurchaseOrder",
                                new XAttribute("PODate", "12/31/2008"),
                                new XAttribute("PONumber", "1111")
                                )
                            );

Here we are creating a PurchaseOrder element with two attributes PODate and PONumber as child element of PurchaseOrders.The output will be:

<PurchaseOrders>
  <PurchaseOrder PODate="12/31/2008" PONumber="1111" />
</PurchaseOrders>

If we pass an object that implements IEnumerable<T> and type is XElement or XAttribute they are added to each elements are added seperately.We can use a LINQ query to add contents as shown below:

XDocument doc = XDocument.Load("Sample1.xml");
XElement po = new XElement("PurchaseOrders",
                                       from elem in doc.Descendants("PurchaseOrder")
                                          select elem
                                        );

In this context we should also understand the difference between node attaching and cloning.When  a node without any parent is added to a tree it is simply attached but one with a parent is deep cloned and then added to the tree.

In our next post we will take a look into advanced features of XLINQ like annotations and event processing.

Sponsor
LINQ To XML Overview

In this post I will discuss about how we can use the concepts of LINQ in parsing an xml document using the classes provided in the System.Xml.Linq namespace.We can think of any xml document as a collection of nodes where a node can be element,attribute,processing instruction,comment or text.Out of these some types of nodes are container nodes which can have child nodes and others cannot.The classes that are used as abstraction for different types of nodes are as follows:

  1. XNode - An abstract class representing an xml node
  2. XContainer - An abstract class representing an xml node that is a container for other nodes
  3. XDocument - Class representing a xml document
  4. XElement - Class representing a xml element
  5. XAttribute -Class representing a xml attribute

Let us consider the following sample xml:

<?xml version="1.0" encoding="utf-8" ?>
<PurchaseOrders>
  <PurchaseOrder PODate="12/31/2008" PONumber="1111"></PurchaseOrder>
  <PurchaseOrder PODate="12/31/2008" PONumber="2222"></PurchaseOrder>
  <PurchaseOrder PODate="12/31/2008" PONumber="3333"></PurchaseOrder>
</PurchaseOrders>

This xml document contains data for a collection of purchase orders.Each purchase order is represented as a child element of PurchaseOrders with attributes PO Date and PONumber.

First we need to load the xml document as shown below:

XDocument doc = XDocument.Load("Sample1.xml");

Now we need to take a closer look into the Descendants method of XDocument class.There are two overloads:

  • public IEnumerable<XElement> Descendants() - Returns a collection of descendant elements of a document or element.
  • public IEnumerable<XElement> Descendants(XName name) - Returns a collection of descendant elements of a document or element filtered by the element name passed parameter.The class XName represents a element or attribute name.This class has no public constructor but performs an implicit conversion from a string passed as value.

The following lines of code will return the child elements of PurchaseOrders.

IEnumerable<XElement> elist = from elem in doc.Descendants("PurchaseOrder")
                              select elem;

foreach (XElement el in elist)
{
    Console.WriteLine(el);
}

The output of the following code will be:


  <PurchaseOrder PODate="12/31/2008" PONumber="1111"></PurchaseOrder>
  <PurchaseOrder PODate="12/31/2008" PONumber="2222"></PurchaseOrder>
  <PurchaseOrder PODate="12/31/2008" PONumber="3333"></PurchaseOrder>

We can very easily use the anonymous types to convert the XML to an object represent as follows:

var polist = from elem in doc.Descendants("PurchaseOrder")
          select new
          {
              PONumber = elem.Attribute("PONumber"),
              PODate   = elem.Attribute("PODate")
          };

In the next post I will discuss about creating and modifying xml documents with LINQ.

Sponsor
Anonymous Types and LINQ

Anonymous types, introduced in C# provides the facility to encapsulate a set of properties into a type without specifically naming the type in source code as shown below:

var prod = new { Name="xyz",Price=12.00};

In this case compiler internally generates code for a type in the IL code.If you check the IL code you'll find a type with name

<>f__AnonymousType0`2'<'<Name>j__TPar','<Price>j__TPar'>

Anonymous types

  • Has to be instantiated with new keyword during declaration
  • Can only contain public read-only properties
  • Are reference types derived from System.Object and Equals returns true if values of all the properties are same.
  • If two anonymous types are declared with same properties in same order then compiler generates code for a single type which is shared between the two e.g. For the code shown below a single type <>f__AnonymousType0`2'<'<Name>j__TPar','<Price>j__TPar'> is generated in IL

          var prod = new { Name="xyz",Price=12.00};
          var prod1 = new { Name = "xyza", Price = 120.00 };

          For the code shown below two types '<>f__AnonymousType0`2'<'<Name>j__TPar','<Price>j__TPar'> and

'<>f__AnonymousType1`2'<'<Price>j__TPar','<Name>j__TPar'> is generated in IL code as order of the properties are different

var prod = new { Name="xyz",Price=12.00};
var prod1 = new { Price = 120.00,Name = "xyza" };

Anonymous types are used LINQ to select a subset of properties from the source object in a query as shown below:

Person[] plist = new Person[] {
                        new Person{FirstName="John",LastName="Doe",City="New York"},
                        new Person{FirstName="Sankarsan",LastName="Bose",City="Kolkata"}};
var per = from p in plist
          select new { p.FirstName, p.City };

In my next post I will be discussing about usage of Generic Types in LINQ.

Sponsor
Dependency Injection

As the concept of TDD(Test Driven Development) is growing popular day by day the Dependency Injection (DI) and Inversion of Control (IoC) patterns are also becoming increasingly popular and much discussed about topic.In this post I will share my thoughts and understanding on this pattern.

Generally in a system developed using the object oriented principles a particular task is carried out by objects interacting or exchanging messages with other objects.An object depends upon other objects to get their job done.A tight coupling between the objects with dependency leads to a rigid design,resistant to future changes.Let us consider the following example:

public class PriceCalculator
   {
       private PriceDAO priceDAO = null;
       public PriceCalculator()
       {
           priceDAO = new PriceDAO();
       }
   }

In this case we have a PriceCalculator which depends on PriceDAO (Price Data Access Object) for the data required to calculate the price.Suppose we need to make the Pricing component flexible enough so that it can compute price by pulling required data (like competitor price,margin,pricing policies etc.) stored in the pricing system or any other external ERP .In this case the data required to perform the pricing may come from different sources and we need PriceDAO,ERPPriceDAO etc. for the different data sources.A rigid coupling between PriceCalculator and PriceDAO is a problem.We can tackle this problem by defining an interface and implementing a factory.

public class PriceCalculator
{
    private IPriceDAO priceDAO = null;
    public PriceCalculator(string datasource)
    {
        this.priceDAO = PriceDAOFactory.CreateInstance(datasource);
    }
}

Thus we have reduced the coupling between PriceCalculator and PriceDAO but now PriceDAOFactory is tightly coupled with PriceDAO.Moreover to incorporate any new data source PriceDAOFactory needs to changed.To solve this problem of dependency with the PriceDAOFactory we can change the code as follows:

public class PriceCalculator
{
    private IPriceDAO priceDAO = null;
    public PriceCalculator(IPriceDAO priceDAO)
    {
        this.priceDAO = priceDAO;
    }
}

Here the code instantiating the PriceCalculator object is responsible creating the correct instance of IPriceDAO and injecting the dependency via PriceCalculator's constructor.This is called "Dependency Injection" or Constructor Dependency injection where the instances of the dependent objects are injected via constructor.There is another variant of Dependency Injection known as Setter Dependency injection where dependent objects are injected via setter properties as shown below:

public class PriceCalculator
{
    private IPriceDAO priceDAO = null;
    public IPriceDAO PriceDataAccessObject
    {
        set
        {
            this.priceDAO = value;
        }
    }
}

Here objects are not responsible for creating their dependent objects but they are created by some external code.This is referred to as "Inversion of Control".The functionality of external code for creating objects is generally taken care by the Dependency Injection containers based on a declarative or configuration based model.Here I will use some snippets based on Spring.NET DI container which instantiates objects based on configuration xml.

<!--<object name="ERPbasedPrice" type="SB.Price.Pricecalculator,PriceEngine">
        <constructor-arg>
          <object type="SB.Price.Data.ERPPriceDAO, PriceEngineData"/>
        </constructor-arg>
      </object>-->

The application code will be

IApplicationContext ctx = ContextRegistry.GetContext()
PriceCalculator calc = (PriceCalculator) ctx.GetObject ("ERPBasedPrice");

Here the ApplicationContext creates the instance of PriceCalculator with the required dependencies based on configuration.

Dependency Injection is a great help for TDD as it makes the Unit Testing of the objects much easier.In this example we can Unit test the PriceCalculator using a Mock data access object without having dependency on the actual database or ERP datasources.

For further reading the following articles will be very useful:

http://martinfowler.com/articles/injection.html

http://msdn.microsoft.com/en-us/magazine/cc163739.aspx

http://msdn.microsoft.com/en-us/library/aa973811.aspx

Sponsor
Lambda Expressions

Before getting details of Lambda expressions let us quickly take a look into how we work with delegates and a named method since the days of .NET 1.1.Let us consider the following code sample

//Delegate declaration

public delegate void Test(string s);

class Program
   {
       static void Main(string[] args)
       {

           //Instantiate the delegate
           Test t = new Test(Print);

           //Invoke the delegate
           t("Hello World");

           Console.Read();
       }
       public static void Print(string s)
       {
           Console.WriteLine(s);
       }
   }

This is how we work delegates and named methods.In C# 2.0 we got the feature of anonymous methods.Using anonymous methods we can directly assign a code block while instantiating a delegate as shown below:

t = delegate(string s) { Console.WriteLine(s); };

This is nothing great but a syntactical sugar coat.If you examine the IL code you will find that compiler has emitted code of another method as shown below:

.method private hidebysig static void  '<Main>b__0'(string s) cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
  // Code size       9 (0x9)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0007:  nop
  IL_0008:  ret
} // end of method Program::'<Main>b__0'

In the IL code of the Main method we can see the following instruction which basically loads the pointer to <Main>b__0 into stack and instantiates the delegate.

IL_0022:  ldftn      void LambdaExpression.Program::'<Main>b__0'(string)

In C# 3.0 we have a new feature , Lambda expressions which are anonymous functions with expressions and statements and can be used to instantiate the delegates as shown below:

t = (x) => { Console.WriteLine(x); };

Lambda Expressions:

  1. Use => operator called "goes to"
  2. Left hand side contains the parameter
  3. Right hand side contains the expression or the statements.

The above code block shows an implicitly typed Lambda expression.But Lambda expressions can be explicitly typed as well:

t = (string x) => { Console.WriteLine(x); };

If you check the IL code for the C# code block above you will find another compiler generated method as in case of anonymous method.Now the obvious question that comes into our mind is what is the difference between anonymous methods and lambda expression?Is it just mere difference in syntax?

The key differences between the two are (from C# 3.0 language spec):

  1. Lambda expressions allows parameter types to be omitted and inferred whereas anonymous methods require parameter types to be explicitly stated.
  2. The body of a Lambda expression can be an expression or a statement block whereas the body of an anonymous methods must be a statement block.e.g. the expression t = (int x) => { return x +2 } is same as t = (int x) => { x + 2 }
  3. Since only Lambda expressions can have an expression body, no anonymous-method-expression can be successfully converted to an expression tree type

The critical difference between the two from compiler design/implementation perspective is explained beautifully by Eric Lippert in his post:

http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx

Sponsor
String Interning in C#

We all know that string objects are immutable in C# i.e we can only create a new instance of the object we cannot alter or modify them.Let us take a quick look into the following lines of code:

static void Main(string[] args)
    {
        string s1 = "sankarsan";
        string s2 = "sankarsan";
        if (object.ReferenceEquals(s1, s2))
        {
            Console.WriteLine("Both s1 and s2 refer to same object");
        }
        else
        {
            Console.WriteLine("s1 and s2 refer to different object");
        }
        Console.Read();
    }

As strings are immutable s1 and s2 should be two different objects and output of the program should be "s1 and s2 refer to different object".But somehow that is not the case the output of the above code is "Both s1 and s2 refer to same object".But how can this happen?Let us also take a look into the IL code

IL_0001:  ldstr      "sankarsan"
IL_0006:  stloc.0
IL_0007:  ldstr      "sankarsan"
IL_000c:  stloc.1

ldstr basically allocates memory for a string and stloc stores the reference into a variable in stack.

Now let us carefully study the documentation of the ldstr opcode in MSDN : http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldstr.aspx.

The following lines in MSDN needs to be carefully noted:

The Common Language Infrastructure (CLI) guarantees that the result of two ldstr instructions referring to two metadata tokens that have the same sequence of characters return precisely the same string object (a process known as "string interning").

CLR internally maintains a hashtable like structure called intern pool which contains an entry for each unique literal string as key and the memory location of the string object as value.When a string literal is assigned to the variable CLR checks if the entry present in the intern pool,if exists it returns reference to that object otherwise creates the string object, adds to the pool and returns the reference.This is String Interning.The basic objective of this is reduce memory usage by avoiding duplication of same strings which are immutable objects.

But this can have negative performance impact as well.This is because the additional hashtable lookups are costly and moreover all the interned strings are not unloaded from the memory till the app domain is unloaded.So they will occupy memory even if they are not used.

We can try to off string interning by adding the following attribute to the assembly

[assembly:CompilationRelaxations(CompilationRelaxations.NoStringInterning)]

But it is upto the CLR as it may or may not consider this attribute.But if the native image is compiled using Ngen.exe then it considers this attribute.

This feature of string interning is not something specific to CLR but also present languages like Java,Python etc.

Sponsor
Object Equality

In this post I will discuss about the very basic concepts related to object equality.Object equality can be of two types

  1. Value Equality - Two objects having same value for all the fields
  2. Reference Equality - Two instance variables pointing to same reference i.e. same memory location in heap.

Let us consider the simple program as shown below:

class Program
    {
        static void Main(string[] args)
        {
            Test t1 = new Test(10);
            Test t2 = new Test(10);
            if (t1.Equals(t2))
            {
                Console.WriteLine("Objects are equal..");
            }
            else
            {
                Console.WriteLine("Objects are not equal..");
            }
            Console.Read();
        }
    }
    class Test
    {
        int i;
        public Test(int i)
        {
            this.i = i;
        }
   }

The output of this program will be:

Objects are not equal..

The default implementation Equals method of System.Object checks if the two objects are referring to same location in heap (Reference Equality).So this will always return correct value.But this method is  a virtual method and we are free to override this.Suppose we override Equals method as follows in Test class:

public override bool Equals(object obj)
{
    if (this.i == ((Test)obj).i) return true;
    return false;
}

The output of this program will change to:

Objects are equal..

So it is always not very wise to rely on the Equals method as it can be overridden.Instead we can also use the static ReferenceEquals method of System.Object.

(object.ReferenceEquals(t1,t2))

The way I have overridden the Equals method is not the ideal way.The detailed guidelines for overriding Equals method can be found at MSDN

http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx

Sponsor
Upcasting and Downcasting in C#

While reviewing code and discussing with developers I have seen in several occasions that people are not very clear or conscious about upcasting and downcasting.In this post I would like to note down the differences between the two.

Upcasting means casting an object of any type to another type which is above it in the inheritance hierarchy.

Downcasting means casting an object of any type to another type which is below it in the inheritance hierarchy.

For sake of simplicity let us consider the two classes as shown below:

public class Base
    {
        public int i;
        public Base()
        {
            i = 10;
        }
    }
    public class Derived:Base
    {
        public int j;
        public Derived()
        {
            j = 10;
        }
    }

Following is the code for upcasting:

Derived d = new Derived();

  Base b = (Base)d;

The corresponding IL code will be as follows:

//Create new object of type
IL_0001:  newobj     instance void TypeConversionDemo.Derived::.ctor()
//Store the reference in first variable
IL_0006:  stloc.0
//Load the value from first variable
IL_0007:  ldloc.0
//store the value in second variable
IL_0008:  stloc.1

Following is the code for downcasting:

object d = new Derived();

Base b = (Base)d;

The corresponding IL code will be as follows:

IL_0001:  newobj     instance void TypeConversionDemo.Derived::.ctor()
IL_0006:  stloc.0
IL_0007:  ldloc.0
IL_0008:  castclass  TypeConversionDemo.Base
IL_000d:  stloc.1

The major difference in the two is presence of the castclass operator.This operator performs a runtime type checking and the types are not compatible then throws a InvalidCastException.For upcasting runtime checking is not required as "derived" is always a type of "base" so question of incompatibility at runtime does not arise.But for downcasting it is not possible to determine at compile time whether two types are compatible.

Let us consider another class:

public class Test
   {
       public int k;
   }

The following code will compile without any error:

       object d = new Derived();

        Test b = (Test)d;

But will throw runtime InvalidCastException.

{"Unable to cast object of type 'TypeConversionDemo.Derived' to type 'TypeConversionDemo.Test'."}

For this runtime check downcasting is always more costly than upcasting in terms of performance.

Sponsor