public static Conversion GetDirect(Type @from, Type to, ITypeMapper typeMapper) { if (to.Equals(from)) { return(new Direct(typeMapper)); } return(new Invalid(typeMapper)); }
// the sections mentioned in comments of this method are from C# specification v1.2 public static Conversion GetImplicit(Operand op, Type to, bool onlyStandard, ITypeMapper typeMapper) { Type from = Operand.GetType(op, typeMapper); Type toUnderlying = Helpers.GetNullableUnderlyingType(to); if (to.Equals(from)) { return(new Direct(typeMapper)); } Type fromUnderlying = Helpers.GetNullableUnderlyingType(@from); if (toUnderlying != null) { if (fromUnderlying != null) { Conversion c = GetImplicit(new FakeTypedOperand(fromUnderlying), toUnderlying, onlyStandard, typeMapper); if (c.IsValid) { return(new ConvertNullable(typeMapper, c)); } } else { Conversion c = GetImplicit(op, toUnderlying, onlyStandard, typeMapper); if (c.IsValid) { return(new WrapNullable(typeMapper, c)); } } } // required for arrays created from TypeBuilder-s if (from != null && to.IsArray && from.IsArray) { if (to.GetArrayRank() == from.GetArrayRank()) { if (to.GetElementType().Equals(from.GetElementType())) { return(new Direct(typeMapper)); } } } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = _convTable[(int)tcFrom][(int)tcTo]; // section 6.1.2 - Implicit numeric conversions if (from != null && (from.IsPrimitive || Helpers.AreTypesEqual(from, typeof(decimal), typeMapper)) && (to.IsPrimitive || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper))) { if (ct <= I) { if (Helpers.AreTypesEqual(from, typeof(decimal), typeMapper) || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper)) { // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; } else { return(new Primitive(typeMapper)); } } } IntLiteral intLit = op as IntLiteral; // section 6.1.3 - Implicit enumeration conversions if (!onlyStandard && to.IsEnum && (object)intLit != null && intLit.Value == 0) { return(new Primitive(typeMapper)); } // section 6.1.4 - Implicit reference conversions if ((from == null || !from.IsValueType) && !to.IsValueType) { if (from == null) // from the null type to any reference type { return(new Direct(typeMapper)); } if (to.IsAssignableFrom(from)) // the rest { return(new Direct(typeMapper)); } } if (from == null) // no other conversion from null type is possible { return(new Invalid(typeMapper)); } // section 6.1.5 - Boxing conversions if (from.IsValueType) { if (to.IsAssignableFrom(from)) { return(new Boxing(typeMapper)); } } // section 6.1.6 - Implicit constant expression conversions if ((object)intLit != null && Helpers.AreTypesEqual(from, typeof(int), typeMapper) && to.IsPrimitive) { int val = intLit.Value; switch (tcTo) { case TypeCode.SByte: if (val >= sbyte.MinValue && val <= sbyte.MaxValue) { return(new Direct(typeMapper)); } break; case TypeCode.Byte: if (val >= byte.MinValue && val <= byte.MaxValue) { return(new Direct(typeMapper)); } break; case TypeCode.Int16: if (val >= short.MinValue && val <= short.MaxValue) { return(new Direct(typeMapper)); } break; case TypeCode.UInt16: if (val >= ushort.MinValue && val <= ushort.MaxValue) { return(new Direct(typeMapper)); } break; case TypeCode.UInt32: if (val >= 0) { return(new Direct(typeMapper)); } break; case TypeCode.UInt64: if (val >= 0) { return(new Direct(typeMapper)); } break; } } // section 6.1.7 - User-defined implicit conversions (details in section 6.4.3) if (onlyStandard || Helpers.AreTypesEqual(from, typeof(object), typeMapper) || Helpers.AreTypesEqual(to, typeof(object), typeMapper) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to)) { return(new Invalid(typeMapper)); // skip not-permitted conversion attempts (section 6.4.1) } List <UserDefined> candidates = null; FindCandidates(ref candidates, FindImplicitMethods(from, to, typeMapper), op, to, GetImplicit, typeMapper); if (candidates == null) { return(new Invalid(typeMapper)); } if (candidates.Count == 1) { return(candidates[0]); } return(UserDefined.FindImplicit(candidates, @from, to, typeMapper)); }
// the sections mentioned in comments of this method are from C# specification v1.2 public static Conversion GetImplicit(Operand op, Type to, bool onlyStandard, ITypeMapper typeMapper) { Type from = Operand.GetType(op, typeMapper); Type toUnderlying = Helpers.GetNullableUnderlyingType(to); if (to.Equals(from)) return new Direct(typeMapper); Type fromUnderlying = Helpers.GetNullableUnderlyingType(@from); if (toUnderlying != null) { if (fromUnderlying != null) { Conversion c = GetImplicit(new FakeTypedOperand(fromUnderlying), toUnderlying, onlyStandard, typeMapper); if (c.IsValid) return new ConvertNullable(typeMapper, c); } else { Conversion c = GetImplicit(op, toUnderlying, onlyStandard, typeMapper); if (c.IsValid) return new WrapNullable(typeMapper, c); } } // required for arrays created from TypeBuilder-s if (from != null && to.IsArray && from.IsArray) { if (to.GetArrayRank() == from.GetArrayRank()) { if (to.GetElementType().Equals(from.GetElementType())) return new Direct(typeMapper); } } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = _convTable[(int)tcFrom][(int)tcTo]; // section 6.1.2 - Implicit numeric conversions if (from != null && (from.IsPrimitive || Helpers.AreTypesEqual(from, typeof(decimal), typeMapper)) && (to.IsPrimitive || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper))) { if (ct <= I) { if (Helpers.AreTypesEqual(from, typeof(decimal), typeMapper) || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper)) // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; else return new Primitive(typeMapper); } } IntLiteral intLit = op as IntLiteral; // section 6.1.3 - Implicit enumeration conversions if (!onlyStandard && to.IsEnum && (object)intLit != null && intLit.Value == 0) return new Primitive(typeMapper); // section 6.1.4 - Implicit reference conversions if ((from == null || !from.IsValueType) && !to.IsValueType) { if (from == null) // from the null type to any reference type return new Direct(typeMapper); if (to.IsAssignableFrom(from)) // the rest return new Direct(typeMapper); } if (from == null) // no other conversion from null type is possible return new Invalid(typeMapper); // section 6.1.5 - Boxing conversions if (from.IsValueType) { if (to.IsAssignableFrom(from)) return new Boxing(typeMapper); } // section 6.1.6 - Implicit constant expression conversions if ((object)intLit != null && Helpers.AreTypesEqual(from, typeof(int), typeMapper) && to.IsPrimitive) { int val = intLit.Value; switch (tcTo) { case TypeCode.SByte: if (val >= sbyte.MinValue && val <= sbyte.MaxValue) return new Direct(typeMapper); break; case TypeCode.Byte: if (val >= byte.MinValue && val <= byte.MaxValue) return new Direct(typeMapper); break; case TypeCode.Int16: if (val >= short.MinValue && val <= short.MaxValue) return new Direct(typeMapper); break; case TypeCode.UInt16: if (val >= ushort.MinValue && val <= ushort.MaxValue) return new Direct(typeMapper); break; case TypeCode.UInt32: if (val >= 0) return new Direct(typeMapper); break; case TypeCode.UInt64: if (val >= 0) return new Direct(typeMapper); break; } } // section 6.1.7 - User-defined implicit conversions (details in section 6.4.3) if (onlyStandard || Helpers.AreTypesEqual(from, typeof(object), typeMapper) || Helpers.AreTypesEqual(to, typeof(object), typeMapper) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to)) return new Invalid(typeMapper); // skip not-permitted conversion attempts (section 6.4.1) List<UserDefined> candidates = null; FindCandidates(ref candidates, FindImplicitMethods(from, to, typeMapper), op, to, GetImplicit, typeMapper); if (candidates == null) return new Invalid(typeMapper); if (candidates.Count == 1) return candidates[0]; return UserDefined.FindImplicit(candidates, @from, to, typeMapper); }
public static Conversion GetDirect(Type @from, Type to, ITypeMapper typeMapper) { if (to.Equals(from)) return new Direct(typeMapper); return new Invalid(typeMapper); }