views:

106

answers:

2

In the solution I have worked out to this question => General type conversion without risking Exceptions (See the edit at the bottom of the question), I need to cache a method for converting between two types.

So, given Type1 and Type2 I need to retrieve a method.

In the answer to this question => What is the best C# collection with two keys and an object? it is recommended to use a dictionary of dictionaries. This is similar to what I am doing.

But I dont like it. It doesnt flow logically with what the collection is meant to represent. Also to retrieve a value I have to do :

        if ( !_Types.ContainsKey ( s.GetType () ) )
        {
            type1Cache = new Dictionary<Type, ConversionCache> ();

            _Types.Add ( s.GetType (), type1Cache );
        }
        else
        {
            type1Cache = _Types[s.GetType ()];
        }

        if ( !type1Cache.ContainsKey ( value.GetType () ) )
        {
            // We havent converted this type before, so create a new conversion
            type2Cache = new ConversionCache ( s.GetType (), value.GetType () );

            // Add to the cache
            type1Cache.Add ( value.GetType (), type2Cache );
        }
        else
        {
            type2Cache = type1Cache[value.GetType ()];
        }

which is a bit long winded.

I just want to do something like

        if ( !_Types.ContainsKey ( s.GetType (), value.GetType() ) )
        {
            cache = new ConversionCache ( s.GetType (), value.GetType () );

            _Types.Add ( s.GetType (), value.GetType(), cache);
        }
        else
        {
            cache = _Types[s.GetType (), value.GetType()];
        }

One solution would be to concatenate the string values of the types. Something like :

        if ( !_Types.ContainsKey ( s.GetType ().ToString() + ":" +  value.GetType().ToString() ) )
        {
            cache = new ConversionCache ( s.GetType (), value.GetType () );
            _Types.Add ( s.GetType ().ToString() + ":" +  value.GetType().ToString(), cache);
        }
        else
        {
            cache = _Types[s.GetType ().ToString() + ":" +  value.GetType().ToString()];
        }

I know it would work in this instance because there is a one-to-one between a type and its string representation.

But that smells pretty bad, and wouldnt work in other situations.

Is there a better way to do this?

+2  A: 

You might want Tuples (in .Net 4) or the one well-known "Pair" class in previous Versions: KeyValuePair.

But - thinking about your requirement, I'd probably go for a custom class. You can make sure that hashcode/equals does what you want, can override ToString() for sensible logging and it probably reads much better anyway.

Benjamin Podszun
+1  A: 

The way you are doing it is fine. If you want a better "smelling" system all you would need is a helper function that takes two inputs (or types) and return a unique string. Then the implementation details of generating the key (in this case concatenating them with a ":" separator) are hidden.

Seems like a little over-engineering to me. I don't believe there is much of a chance you will need to change this key generation method and you are not trying to make a generic class. Clearly you would need to do it with a generic class.

Hogan