Static Generic Class as Dictionary

Static Generic Class as Dictionary

I like using generic types this way. In particular, I often have private nested generic classes for precisely this purpose.

The main thing I like about it is that it's hard not to get the initialization right this way (in terms of thread safety), given the way type initialization works. The only problem is what to do if initialization fails - occasionally I've resorted to remembering an exception to throw on first necessary access, but that's pretty rare.

I wouldn't like to guess at exactly how the CLR looks up the type via the type arguments, but I'm pretty sure it'll be optimised to heck and back :)

How to create a generic static dictionary in a static class

You haven't declared Tracking as a generic type, so T, K and V have no meaning. You can do so easily enough:

public static class Tracking<T, K, V>
{
...
}

Note that you'll now have separate Lists, Dictionaries etc fields per concrete type. You'll need to make the methods non-generic though.

An alternative is to have a top-level non-generic class, with generic methods and generic nested types:

public static class Tracking
{
private static class ListHelper<T>
{
internal static List<TrackList<T>> Lists = new List<TrackList<T>>();
}

private static class DictionaryHelper<K, V>
{
internal static List<TrackedDictionary<K,V>> Dictionaries =
new List<TrackedDictionary<K,V>>()
}

public static void Register<K,V>(TrackedDictionary<K,V> dictionary)
{
DictionaryHelper<K, V>.Dictionaries.Add(dictionary);
}

public static void Register<T> (TrackList<T> list)
{
ListHelper<T>.Lists.Add(list);
}
}

I'd also strongly advise against public fields like this... and against using statics widely to start with, given the problems they cause for testability.

Uses for static generic classes?

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.

how to use generic in static class

You need both the generic and non-generic versions of the class. The non-generic class calls the constructor of the generic one, therefore, it must be there.

This should work:

public class Wrapper<T>
{
public Wrapper(T wrapped)
{
Wrapped = wrapped;
}

public T Wrapped { get; set; }
}

public class Wrapper
{
public static Wrapper<T> Create<T>(T wrapped)
{
return new Wrapper<T>(wrapped);
}
}

Which you can use it like this as shown in the article you referred to:

var wrappedInt = Wrapper.Create(42);

Static generic using Type

My suggestion is to maintain a static Dictionary what would hold the Ancestral Type List per subclass. It would be used to cache the types and therefore avoid building the lists repeatedly, which would mean some performance gain.

Something like this:

static Dictionary<string (TypeName), Type[]>

Can I Create a Dictionary of Generic Types?

EDIT: Now I've reread the question...

You can't do this, but a custom collection would handle it to some extent. You'd basically have a generic Add method:

public void Add<T>(string key, List<T> list)

(The collection itself wouldn't be generic - unless you wanted to make the key type generic.)

You couldn't extract values from it in a strongly typed manner though, because the compiler won't know which type you've used for a particular key. If you make the key the type itself, you end with a slightly better situation, but one which still isn't supported by the existing collections. That's the situation my original answer was responding to.

EDIT: Original answer, when I hadn't quite read the question correctly, but which may be informative anyway...

No, you can't make one type argument depend on another, I'm afraid. It's just one of the things one might want to express in a generic type system but which .NET's constraints don't allow for. There are always going to be such problems, and the .NET designers chose to keep generics relatively simple.

However, you can write a collection to enforce it fairly easily. I have an example in a blog post which only keeps a single value, but it would be easy to extend that to use a list.

C# generic type constraint depending on used constructor

One way is to keep only the constructor taking the value factory in DefaultDictionary, and create a subclass that does have the : new() constraint, and move the parameterless constructor there:

public class DefaultDictionaryParameterless<TKey, TValue> :
DefaultDictionary<TKey, TValue> where TValue : new()
{
public DefaultDictionaryParameterless()
: base(x => new TValue())
{

}
}

public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private readonly Func<TKey, TValue> factory;

public DefaultDictionary(Func<TKey, TValue> factory)
{
this.factory = factory;
}
...
}

Dictionary of classes that implement a generic interface

There may be something obvious I'm missing in your question, because I don't understand where the issue is.

First, I declare a IResolver<TIn, TOut> interface with a constraint:

public interface IResolver<TIn, TOut>
where TIn : Stream
{

}

Then, I create a ResolverFactory, where the constraints are enforced by both the RegisterResolver and GetResolver method. The way the objects are actually stored doesn't matter, because the storage isn't exposed outside of the class. The encapsulation maintains the consistency:

public static class ResolverFactory
{
private static Dictionary<Type, object> storage = new Dictionary<Type, object>();

public static void RegisterResolver<TIn, TOut>(IResolver<TIn, TOut> resolver) where TIn : Stream
{
storage[typeof(IResolver<TIn, TOut>)] = resolver;
}

public static IResolver<TIn, TOut> GetResolver<TIn, TOut>() where TIn : Stream
{
return storage[typeof(IResolver<TIn, TOut>)] as IResolver<TIn, TOut>;
}
}


Related Topics



Leave a reply



Submit