Monday, February 25, 2013

Cloning objects in .NET

In .NET I want to do something like:
// This is illegal in C#
public class PdfDetails : ICloneable<PdfDetails>
{
    public int Id { get; set; }
    public string FileName { get; set; }

    public PdfDetails Clone()
    {
        return MemberwiseClone();
    }
}
But I can't because IClonable is not a generic interface. I remember reading explanation for it in Skeets book or Eric Lipper blog, and it was because in .NET framework before 2.0 there was no generics and since then some of the old interfaces were replaced with generic once, in other cases new generics interfaces were created, and in some cases nothing happened - and ICloneable is an example of this group, there is no support or replacement for generics. So I need to do something like:
public class PdfDetails : ICloneable
{
    public int Id { get; set; }
    public string FileName { get; set; }

    public object Clone()
    {
        return MemberwiseClone();
    }
}
Unfortunately I do not want to return an object type I want to return a PdfDetails type but I can't do it with a non generic interface. So I need to do overloading to create a method that returns a PdfDetails type, the thing that I am really thinking of is something like:
public class PdfDetails : ICloneable
{
    public int Id { get; set; }
    public string FileName { get; set; }

    public object Clone()
    {
        return MemberwiseClone();
    }

    // This is illegal in C#
    public PdfDetails Clone()
    {
     return (PdfDetails) Clone();
    }
}
But I can't do it in C#, because it is not how overloading works here. So I need to do something like:
public class PdfDetails : ICloneable
{
    public int Id { get; set; }
    public string FileName { get; set; }

    // unfortunately this method can not be public
    object ICloneable.Clone()
    {
       return MemberwiseClone();
    }

    public PdfDetails Clone()
    {
        // because ICloneable.Clone() can not be public I can not call it from here
        // instad I need to call again MemberwiseClone() method
        return (PdfDetails)MemberwiseClone();
    }
}
But when you look at the code above you ask a question then why do I really want to implement a ICloneable interface in first place. And I belive, that you don't have to if you don't need to. What I mean is you can go and safely write a code like:
public class PdfDetails 
{
    public int Id { get; set; }
    public string FileName { get; set; }

    public PdfDetails Clone()
    {
        return (PdfDetails)MemberwiseClone();
    }
}
It does the job, but it doesn't inform other programmers that PdfDetails class is supposed to Clone objects. That's why I enjoy writing my own interface:
public interface ICloneable<out T>
{
    T Clone();
}
And than implement it
public class PdfDetails : ICloneable<PdfDetails>
{
    public PdfDetails Clone()
    {
 return (PdfDetails)MemberwiseClone();
    }
}

Thursday, February 14, 2013

How ASP.NET lifecycle works

Today I had to explain it to few people, so I thought that it would be good to have a place to write it down, so I don't need to do it next time:)

Global.asax.cs includes a class (usually called Global) that inherits from HttpApplication. The hard part is that HttpApplication can only handle one request per time. The confusing part is that this class includes methods that should be executed just once per application lifecycle, and if HttpApplication is able to handle only one request per time, how is it possible that everything works, and how is it possible that IIS is able to handle multiple requests pert time?

First things first, methods like Application_Start, Application_End are called once per AppDomain lifecycle, programmer should not be concerned that they exist in a scope of a class (usually called Global) that can be created many times. So these methods are different than for example modules that are executed once per HttpApplication. And it leads us to a second thought, class that exists in Global.asax (usually called Global) should be treated as an ordinary class, it means that its object can be created and destroyed at any time.

When a new request is send to IIS, and Global class object is busy handling other request, IIS can create a new thread and create a new instance of Global class. IIS can create such thread, but doesn't have to, it can stack a request and wait to reuse Global object that will finish handling previous requests.

To make it even more complicated each AppDomain that was created by ASP.NET can have multiple Global objects, so it is extremely easy to 'configure' something wrong, especially when you use static keyword, or a singleton pattern! Now it is also important to notice that one application can run as many AppDomains, but it is not very useful configuration (in majority of cases), but one IIS can host multiple applications, and each of them 'should' run in a separate AppDomain.

Hope it clarifies something :)