public static Conversion GetExplicit(Operand op, Type to, bool onlyStandard) { // try implicit Conversion conv = GetImplicit(op, to, onlyStandard); if (conv.IsValid) { return(conv); } Type from = Operand.GetType(op); // section 6.3.2 - Standard explicit conversions if (onlyStandard) { if (from == null || !GetImplicit(to, from, true).IsValid) { return(Invalid.Instance); } } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = convTable[(int)tcFrom][(int)tcTo]; // section 6.2.1 - Explicit numeric conversions, 6.2.2 - Explicit enumeration conversions if ((from.IsPrimitive || from.IsEnum || from == typeof(decimal)) && (to.IsPrimitive || to.IsEnum || to == typeof(decimal))) { if (ct == D) { return(Direct.Instance); // this can happen for conversions involving enum-s } if (ct <= E) { if (from == typeof(decimal) || to == typeof(decimal)) { // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; } else { return(Primitive.Instance); } } } // section 6.2.5 - User-defined explicit conversions (details in section 6.4.4) if (!(onlyStandard || from == typeof(object) || to == typeof(object) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to))) { List <UserDefined> candidates = null; FindCandidates(ref candidates, FindExplicitMethods(from, to), op, to, GetExplicit); if (candidates != null) { if (candidates.Count == 1) { return(candidates[0]); } return(UserDefined.FindExplicit(candidates, from, to)); } } // section 6.2.3 - Explicit reference conversions, 6.2.4 - Unboxing conversions // TODO: not really according to spec, but mostly works if (!from.IsValueType && from.IsAssignableFrom(to)) { if (to.IsValueType) { return(Unboxing.Instance); } else { return(Cast.Instance); } } return(Invalid.Instance); }