views:

280

answers:

3

Hi all,

I have been wondering, When to use static functions and when not to in ASP.NET

What are the advantages and disadvantages in using them, in various aspects like performance, following good practices etc (and many more, which ever you feel is relevant).

Looking forward for your replies.

Thanks,
Mahesh Velaga.

+4  A: 

Cons:

  • threading issues (static functions don't require an instance to be called on, so it is easy to invoke them from different parts of the code and if they read/write to a shared state this state might be corrupted in a multi-threaded environment such as ASP.NET)
  • difficult to unit test (as static functions don't require an object instance, constructor injection is impossible meaning that the only way to inject dependencies is by passing them as arguments to the function itself)

Pros:

  • performance (this is questionable - in most cases performance gains will be completely negligible compared to other parts of the code)
Darin Dimitrov
could you please elaborate on that, or could you provide some pointers in that direction .. thanks
Mahesh Velaga
Wouldn't another benefit be semantics: Some behaviors are not dependent on an enclosing instance to function, so it's more "correct" to mark them as such.
ehdv
@ehdv that is an extension of performance - merely eliminating unnecessary instances.
Rex M
+1  A: 

The only major disadvantage to a static method is that it's almost entirely non-unit testable. Users of the method have to bind to the concrete method and cannot bind to an abstraction, thus making faking or mocking difficult if not impossible.

This may or may not be an issue, depending on the code, however.

The other thing you want to watch out for is that static data is universal across all requests to the server.

Randolpho
It's also extremely confusing for beginning ASP.NET developers.
Rex M
+2  A: 

There are definitely situations where static is the appropriate solution, as with any application. Any time you have some object that ought to live at the application scope, and not at the request scope, it should be static and you should use static methods to access and manipulate it.

As an example, here's a snippet of code I wrote recently for an ASP.NET application, which is essentially a serializer cache. Serializers are expensive to create and we can reuse the same one per type for as long as our application lives, so there's no need to waste time in each request thread for them:

(Note: this has been stripped down to demonstrate the static aspects)

public class XmlSerializerUtility
{
    private static Dictionary<Type, XmlSerializer> serializers = new Dictionary<Type, XmlSerializer>();
    private static object sync = new object();

    public static T Deserialize<T>(string input)
    {
       XmlSerializer xs = GetSerializer(typeof(T));
        using (StringReader sr = new StringReader(input))
        {
            return (T)xs.Deserialize(sr);
        }
    }

    public static XmlDocument Serialize(object input)
    {
        XmlDocument doc = new XmlDocument();
        XmlSerializer xs = GetSerializer(input.GetType());
        using (MemoryStream stream = new MemoryStream())
        {
            xs.Serialize(stream, input);
            stream.Position = 0;
            doc.Load(stream);
        }
        return doc;
    }

    private static XmlSerializer GetSerializer(Type type)
    {
        lock (sync)
        {
            XmlSerializer xs = null;
            if (!serializers.ContainsKey(type))
            {
                xs = new XmlSerializer(type);
                serializers.Add(type, xs);
            }
            else
            {
                xs = serializers[type];
            }
            return xs;
        }
    }
}
Rex M
@Rex M, your `Dictionary<Type, XmlSerializer>` is pointless, XmlSerializer already uses advanced caching techniques and it won't create twice the same temp assembly for the same types. A simple `new XmlSerializer(type)` will do the job just fine. I've once did the same thing only to find out that the `lock` statement was as slow as newing the serializer :-)
Darin Dimitrov
@Darin I think you may be mistaken. The XmlSerializerFactory does indeed use caching, but does not support generic types very well. The XmlSerializer (no factory) does not cache.
Rex M
@Rex M, according to the documentation (http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx) if you use any of the ctors: `XmlSerializer.XmlSerializer(Type)` or `XmlSerializer.XmlSerializer(Type, String)` which you do : the XML serialization infrastructure dynamically generates assemblies to serialize and deserialize specified types. The infrastructure finds and reuses those assemblies.
Darin Dimitrov
The documentation does indeed provide an example caching the serializers but it uses a special constructor: `XmlSerializer(Type, XmlRootAttribute)`
Darin Dimitrov
@Darin thanks for the link. The code sample I've provided is extremely stripped down - the real one does have other dimensions and uses other XmlSerializer ctors. This class was built after profiling the application, and produced measurable gains- so it is certainly not pointless. The only purpose here is to demonstrate a situation where static is useful in ASP.NET, nothing more.
Rex M
@Rex, I understand, I apologize for my confusion, but I couldn't know this. It's really great that you did profiling. That's exactly what people should do in order to verify their code.
Darin Dimitrov