Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uses for static generic classes?

What are the key uses of a Static Generic Class in C#? When should they be used? What examples best illustrate their usage?

e.g.

public static class Example<T> {    public static ... } 

Since you can't define extension methods in them they appear to be somewhat limited in their utility. Web references on the topic are scarce so clearly there aren't a lot of people using them. Here's a couple:-

http://ayende.com/Blog/archive/2005/10/05/StaticGenericClass.aspx

Static Generic Class as Dictionary


Summary of Answers Given

The key issues appear to be "What's the difference between a static generic class with static methods and a non-generic static class with static generic members?"

The decision as to which to use appears to revolve around "Does the class need to store type-specific state internally?"

If there is no need for type-specific internal storage then a static non-generic class with generic static methods appears to be preferable because the calling syntax is nicer and you can define extension methods within it.

like image 685
Ian Mercer Avatar asked Apr 21 '10 17:04

Ian Mercer


People also ask

What are static classes used for?

A static class can be used as a convenient container for sets of methods that just operate on input parameters and do not have to get or set any internal instance fields. For example, in the . NET Class Library, the static System.

Can static classes be generic?

A static generic class is exactly as useful as any given static class. The difference is that you don't have to use copy-and-paste to create a version of the static class for each type you want it to work on. You make the class generic, and you can "generate" one version for each set of type parameters.

What are generics useful for?

Generics enable the use of stronger type-checking, the elimination of casts, and the ability to develop generic algorithms. Without generics, many of the features that we use in Java today would not be possible.

Can you use generics in static method?

Static and non-static generic methods are allowed, as well as generic class constructors. The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type.


2 Answers

I use static generic classes for caching reflection-heavy code.

Let's say I need to build an expression tree that instantiates objects. I build it once in the static constructor of the class, compile it to a lambda expression, then cache it in a member of the static class. I often don't make these classes publicly assessable - they are usually helpers for other classes. By caching my expressions in this way, I avoid the need to cache my expressions in some sort of Dictionary<Type, delegate>.

There is an example of this pattern in the BCL. The (DataRow) extension methods Field<T>() and SetField<T>() use the (private) static generic class System.Data.DataRowExtensions+UnboxT<T>. Check it out with Reflector.

like image 131
Greg Avatar answered Sep 26 '22 07:09

Greg


Making a class static doesn't add any functionality - it's just a convenient check if you intend to use a class without instantiating it. And there are several uses for that...

You can use static generic classes to work around a limitation: C# doesn't permit partial specialization. That means you must either specify all type parameters or none. However, that can be needlessly verbose.

For example:

static class Converter {     public TOut Convert<TIn, TOut>(TIn x) {...} } 

the previous class doesn't permit type inference since inference doesn't work on return values. However, you also can't specify the return value type without also specifying the input type since you can't partially specialize. Using a (possibly static) generic class, you can specify only one of the two types:

static class ConvertTo<TOut> {     public TOut Convert<TIn>(TIn x) {...} } 

That way you can let type inference work on the parameter type and specify only the return type.

(Although the above case is conceivable, it doesn't require the generic class to be static, of course).


Secondly, (as Steven first pointed out) a separate static fields exists for each constructed type, and that makes static classes great places to store extra information about types or type combinations. In essence, it's a semi-static hashtable that keys on types.

A semi-static lookup table keying on types sounds a little arcance, but it's actually a very, very useful structure because it allows you to store expensive reflection and code-generation results where they're almost free to look up (cheaper than a dictionary because it gets JIT-ed in and you avoid a call to .GetType()). If you're doing metaprogramming, this is great!

For example, I use this in ValueUtils to store generated hash functions:

//Hash any object: FieldwiseHasher.Hash(myCustomStructOrClass);  //implementation: public static class FieldwiseHasher {     public static int Hash<T>(T val) { return FieldwiseHasher<T>.Instance(val); } }  public static class FieldwiseHasher<T> {     public static readonly Func<T, int> Instance = CreateLambda().Compile();     //... } 

Static generic methods allow type-inference to make usage really easy; static fields on generic classes allow virtually overhead-free storage of (meta)data. It wouldn't surprise me at all if ORM's like Dapper and PetaPoco use techniques like this; but it's also great for (de)serializers. A limitation is that you're getting the low overhead because you're binding to the compile-time type; if the object that's passed is actually an instance of a subclass, you're probably binding to the wrong type - and adding checks to avoid that kind of undermines the benefit of being low-overhead.

like image 27
Eamon Nerbonne Avatar answered Sep 23 '22 07:09

Eamon Nerbonne