Mapping from a type to an instance of that type

A question came up on Stack Overflow yesterday which I’ve had to deal with myself before now. There are times when it’s helpful to have one value per type, and that value should be an instance of that type. To express it in pseudo-code, you want an IDictionary<typeof(T), T> except with T varying across all possible types. Indeed, this came up in Protocol Buffers at least once, I believe.

.NET generics don’t have any way of expressing this, and you end up with boxing and a cast. I decided to encapsulate this (in MiscUtil of course, although it’s not in a released version yet) so that I could have all the nastiness in a single place, leaving the client code relatively clean. The client code makes calls to generic methods which either take an instance of the type argument or return one. It’s a really simple class, but a potentially useful one:

/// <summary>
/// Map from types to instances of those types, e.g. int to 10 and
/// string to “hi” within the same dictionary. This cannot be done
/// without casting (and boxing for value types) as .NET cannot
/// represent this relationship with generics in their current form.
/// This class encapsulates the nastiness in a single place.
/// </summary>
public class DictionaryByType
{
    private readonly IDictionary<Type, object> dictionary = new Dictionary<Type, object>();

    /// <summary>
    /// Maps the specified type argument to the given value. If
    /// the type argument already has a value within the dictionary,
    /// ArgumentException is thrown.
    /// </summary>
    public void Add<T>(T value)
    {
        dictionary.Add(typeof(T), value);
    }

    /// <summary>
    /// Maps the specified type argument to the given value. If
    /// the type argument already has a value within the dictionary, it
    /// is overwritten.
    /// </summary>
    public void Put<T>(T value)
    {
        dictionary[typeof(T)] = value;
    }

    /// <summary>
    /// Attempts to fetch a value from the dictionary, throwing a
    /// KeyNotFoundException if the specified type argument has no
    /// entry in the dictionary.
    /// </summary>
    public T Get<T>()
    {
        return (T) dictionary[typeof(T)];
    }

    /// <summary>
    /// Attempts to fetch a value from the dictionary, returning false and
    /// setting the output parameter to the default value for T if it
    /// fails, or returning true and setting the output parameter to the
    /// fetched value if it succeeds.
    /// </summary>
    public bool TryGet<T>(out T value)
    {
        object tmp;
        if (dictionary.TryGetValue(typeof(T), out tmp))
        {
            value = (T) tmp;
            return true;
        }
        value = default(T);
        return false;
    }
}

It doesn’t implement any of the common collection interfaces, because it would have to do so in a way which exposed the nastiness. I’m tempted to make it implement IEnumerable<KeyValuePair<Type, object>> but even that’s somewhat unpleasant and unlikely to be useful. Easy to add at a later date if necessary.

(I know the XML documentation leaves something to be desired. One day I’ll learn how to really do it properly – currently I fumble around if I’m trying to refer to other types etc within the docs.)

18 thoughts on “Mapping from a type to an instance of that type”

  1. Is there a particular reason why you typed a private readonly object that’s only ever a Dictionary as the interface it implements?

  2. @Jesper: Just general principle. I tend to like to use interfaces where I can. It (hopefully) makes it clear to anyone reading the code that I’m not relying on any particular extras supplied by Dictionary.

  3. I’d expect the Dictionary type to track the generic IDictionary interface fairly closely. Fair enough, I suppose, since other interfaces and classes don’t necessarily.

  4. If you have a weak dictionary implementation (one that uses weak-reference keys and cleans out otherwise unreferenced keys and their associated values), you could try something like this to avoid casts:

    public class TypeDictionary
    {
    private class InnerTypeDictionary
    {
    static WeakDictionary _innerDictionary = new WeakDictionary();
    public static void Add(TypeDictionary dic, T value)
    {
    _innerDictionary.Add(dic, value);
    }

    public static T GetValue(TypeDictionary dic)
    {
    return _innerDictionary[dic];
    }
    }

    public void Add(T value)
    {
    InnerTypeDictionary
    .Add(this, value);
    }

    public T GetValue()
    {
    return InnerTypeDictionary
    .GetValue(this);
    }
    }

  5. Ooh, interesting. I’d thought of the use of generic statics, but run into the “values per dictionary” issue – which you’ve neatly sidestepped.

    I think I probably prefer the cast to using weak references, but that’s a really interesting approach :)

  6. Agreed, it’s a lot of effort to go to just to avoid a cast – though the possibility of avoiding boxing primitives in the dictionary might be a more tempting reason to use it, the weak key cleanup would probably introduce a horrendous overhead in any implementation that was using enough instances of this type to benefit from the savings due to boxing :)

    That approach is actually derived from one that came up when trying to come up with a state mechanism for extension methods, where the idea of a weak dictionary makes more sense.

  7. “Hi, It looks like you’re writing an IOC container!
    For service locator functions it might be useful to take a look at using the CommonServiceLocator interface http://www.codeplex.com/CommonServiceLocator. Not only is this nice and clear, but also will minimise friction if you decide to use an existing IOC container later.”

  8. @Clippy: That’s certainly one use for it (and the one in the SO question). As it happens, my use was somewhat different, and not service based :)

  9. What do you do when someone decides to store an IDisposable object in this dictionary? Should this dictionary be disposable and dispose of any disposable values when the time is appropriate?

  10. Todd: The dictionary shouldn’t care about any more than the .NET Dictionary class cares if you add references to IDisposable instances. It’s up to the client to clean up.

  11. With a traditional dictionary it seems much more clear who is the owner of the lifetime of the objects within the dictionary. In the case of a dictionary that contains the sole reference to IDisposables it is obvious that they all need to be disposed when the dictionary is no longer needed.

    It seems like with this dictionary the benefit partially lies in the ability of not knowing what people would put in it.

    The main reason why IDisposable came to mind was that the StackOverflow post adds a SqlConnection to the dictionary.

    Maybe my real concern is that this type of dictionary is not suitable for IDisposables at all, or at least not database connections. Maybe it would seem more correct if it was an object that created database connections.

  12. Jon,

    What advantage does your method have over generic statics?

    public static class OneAndOnly
    {
    private static class Content
    {
    static bool HasValue;
    static T Value;
    }

    public void Add(T value)
    {
    if (Content
    .HasValue)
    throw new DuplicateKeyException();
    Put(value);
    }

    public void Put(T value)
    {
    Content
    .Value = value;
    Content
    .HasValue = true;
    }

    public T Get()
    {
    if (Content
    .HasValue)
    throw new KeyNotFoundException();
    return Content
    .Value;
    }

    public bool TryGet(out T value)
    {
    value = Content
    .Value;
    return Content
    .HasValue;
    }

    public void Remove()
    {
    Content
    .HasValue = false;
    }
    }

  13. Ben: That limits you to a single type/value mapping. DictionaryByType lets you have as many dictionaries as you want.

  14. Pavel: I can’t say I’ve used KeyedByTypeCollection before, but it looks like the values are all the same type (TItem) as opposed to the value for a particular key being an instance of that key (type).

  15. TItem that you give is the common base type for all types in the collection. Naturally, you can just use Object if you don’t want any restrictions whatsoever (which is rare – more often, when you use such a thing as e.g. a factory class registry, you have some common base interface you want to enforce). But otherwise it’s precisely the same – the key for the item is its type as returned by GetType(), and there can only be one item of a given type. E.g.:

    using System;
    using System.Collections.Generic;

    static class Program
    {
    static void Main()
    {
    var d = new KeyedByTypeCollection();

    d.Add(123);
    d.Add(123.456);
    d.Add(‘x’);
    d.Add(“foo”);

    Console.WriteLine(d.Find());
    Console.WriteLine(d.Find());
    Console.WriteLine(d.Find());
    Console.WriteLine(d.Find());

    d.Remove();
    d.Remove();
    d.Remove();

    d.Add(‘y’); // throws
    }
    }

  16. Pavel: I’ve had another look at KeyedByTypeCollection, and it does look somewhat like it, yes. It’s a shame the docs are so poor. (It’s really unclear what it’s actually doing to start with.)

    Personally I prefer the API of DictionaryByType – it makes it clearer what’s going on, IMO, and it doesn’t artificially implement the other collection interfaces (which can’t really express what’s going on cleanly). My class also has an interface close to the Dictionary API, with TryGetValue for example. (I’d have used an indexer instead of Get/Put, but they can’t be generic.)

    Worth knowing about, though – thanks.

Comments are closed.