public static bool TryGetTypeConversion(Type fromType, Type toType, out TypeConversion typeConversion)
        {
            if (fromType == null)
            {
                throw new ArgumentNullException("fromType");
            }
            if (toType == null)
            {
                throw new ArgumentNullException("toType");
            }

            var key = new TypeTuple2(fromType, toType);

            lock (Conversions)
                return(Conversions.TryGetValue(key, out typeConversion));
        }
        private static void SetNaturalConversion(float quality, Type fromType, params Type[] toTypes)
        {
            if (fromType == null)
            {
                throw new ArgumentNullException("fromType");
            }
            if (toTypes == null)
            {
                throw new ArgumentNullException("toTypes");
            }

            foreach (var toType in toTypes)
            {
                var key = new TypeTuple2(fromType, toType);
                Conversions.Add(key, new TypeConversion(quality, isNatural: true));
            }
        }
        internal static void UpdateConversions(IEnumerable <TypeDescription> typeDescriptions)
        {
            if (typeDescriptions == null)
            {
                throw new ArgumentNullException("typeDescriptions");
            }

            lock (Conversions)
            {
                foreach (var typeDescription in typeDescriptions)
                {
                    foreach (var conversionMethod in typeDescription.Conversions)
                    {
                        var key = new TypeTuple2(conversionMethod.GetParameterType(0), conversionMethod.GetParameterType(-1));

                        var explicitConversionMethod = conversionMethod.IsImplicitOperator ? default(MemberDescription) : conversionMethod;
                        var implicitConversionMethod = conversionMethod.IsImplicitOperator ? conversionMethod : default(MemberDescription);
                        var conversion    = default(TypeConversion);
                        var newConversion = default(TypeConversion);
                        var cost          = conversionMethod.IsImplicitOperator ? TypeConversion.QUALITY_IMPLICIT_CONVERSION : TypeConversion.QUALITY_EXPLICIT_CONVERSION;
                        if (Conversions.TryGetValue(key, out conversion) == false)
                        {
                            newConversion = new TypeConversion(cost, false, implicitConversionMethod, explicitConversionMethod);
                        }
                        else
                        {
                            newConversion = conversion.Expand(implicitConversionMethod, explicitConversionMethod);
                        }

                        if (newConversion != conversion)
                        {
                            Conversions[key] = newConversion;
                        }
                    }

                    foreach (var baseType in typeDescription.BaseTypes)
                    {
                        var key        = new TypeTuple2(typeDescription, baseType);
                        var cost       = baseType == typeDescription ? TypeConversion.QUALITY_SAME_TYPE : TypeConversion.QUALITY_INHERITANCE_HIERARCHY;
                        var conversion = default(TypeConversion);
                        if (Conversions.TryGetValue(key, out conversion))
                        {
                            conversion = new TypeConversion(cost, true, conversion.Implicit, conversion.Explicit);
                        }
                        else
                        {
                            conversion = new TypeConversion(cost, true, null, null);
                        }
                        Conversions[key] = conversion;
                    }

                    foreach (var baseType in typeDescription.Interfaces)
                    {
                        var key        = new TypeTuple2(typeDescription, baseType);
                        var cost       = baseType == typeDescription ? TypeConversion.QUALITY_SAME_TYPE : TypeConversion.QUALITY_INHERITANCE_HIERARCHY;
                        var conversion = default(TypeConversion);
                        if (Conversions.TryGetValue(key, out conversion))
                        {
                            conversion = new TypeConversion(cost, true, conversion.Implicit, conversion.Explicit);
                        }
                        else
                        {
                            conversion = new TypeConversion(cost, true, null, null);
                        }
                        Conversions[key] = conversion;
                    }

                    if (typeDescription.IsEnum)
                    {
                        var fromEnumKey = new TypeTuple2(typeDescription, typeDescription.UnderlyingType);
                        var toEnumKey   = new TypeTuple2(typeDescription.UnderlyingType, typeDescription);

                        Conversions[fromEnumKey] = new TypeConversion(TypeConversion.QUALITY_IN_PLACE_CONVERSION, true);
                        Conversions[toEnumKey]   = new TypeConversion(TypeConversion.QUALITY_IN_PLACE_CONVERSION, true);
                    }
                }
            }
        }