/// <summary> /// 返回 <paramref name="types"/> 中能够被其它所有类型包含的类型。 /// </summary> /// <param name="types">类型集合。</param> /// <returns><paramref name="types"/> 中能够被其它所有类型包含的类型,如果不存在则为 <c>null</c>。</returns> /// <exception cref="ArgumentNullException"><paramref name="types"/> 为 <c>null</c>。</exception> /// <remarks>若 A 类型可以隐式类型转换(指预定义的类型转换)为 B 类型,那么就称 A 被 B 包含,而 B 包含 A。</remarks> public static Type GetEncompassedType(IEnumerable <Type> types) { if (types == null) { throw CommonExceptions.ArgumentNull("types"); } Contract.EndContractBlock(); Type encompassedType = null; foreach (Type type in types) { if (type == null) { continue; } if (encompassedType == null) { encompassedType = type; } else if (encompassedType != type) { // 这里剔除 void 类型,但若 types 全部是 void,能够使得结果是 void。 if (encompassedType == typeof(void)) { encompassedType = type; } else if (type != typeof(void)) { ConversionType convType = ConversionFactory.GetStandardConversion(encompassedType, type); if (convType == ConversionType.None) { return(null); } if (convType.IsExplicit()) { encompassedType = type; } } } } return(encompassedType); }
/// <summary> /// 寻找与 <paramref name="type"/> 匹配的最好的类型。调用保证 <paramref name="type"/> /// 可以转换为 <paramref name="firstType"/> 和 <paramref name="secondType"/>。 /// </summary> /// <param name="firstType">要比较匹配的第一个类型。</param> /// <param name="secondType">要比较匹配的第二个类型。</param> /// <param name="type">要进行匹配的类型。</param> /// <returns>如果 <paramref name="firstType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>-1</c>; /// 如果 <paramref name="secondType"/> 与 <paramref name="type"/> 匹配的更好,则为 <c>1</c>; /// 如果匹配程度相同,则为 <c>0</c>。</returns> /// <remarks>《CSharp Language Specification》 7.5.3.3 Better conversion from expression。</remarks> private int CompareType(Type firstType, Type secondType, Type type) { Contract.Requires(firstType != null && secondType != null && type != null); Contract.Ensures(Contract.Result <int>() >= -1 && Contract.Result <int>() <= 1); if (firstType == secondType) { return(0); } if (firstType == type) { return(-1); } if (secondType == type) { return(1); } bool typeByRef = type.IsByRef; // 根据 type 是否按引用传递,选择普通参数或按引用传递的参数。 if (firstType.IsByRef) { firstType = firstType.GetElementType(); if (secondType.IsByRef) { secondType = secondType.GetElementType(); } else if (firstType == secondType) { return(typeByRef ? -1 : 1); } } else if (secondType.IsByRef) { secondType = secondType.GetElementType(); if (firstType == secondType) { return(typeByRef ? 1 : -1); } } if (typeByRef) { type = type.GetElementType(); } bool firstImplicitFromType = true; if (isExplicit) { // 可以从 type 隐式转换的类型会更匹配,仅当允许显式类型转换时才需要检测。 firstImplicitFromType = firstType.IsImplicitFrom(type); if (firstImplicitFromType != secondType.IsImplicitFrom(type)) { return(firstImplicitFromType ? -1 : 1); } } ConversionType convType = TypeExt.GetStandardConversion(firstType, secondType); if (convType == ConversionType.None) { if (firstType.IsSigned()) { if (secondType.IsUnsigned()) { return(-1); } } else if (firstType.IsUnsigned() && secondType.IsSigned()) { return(1); } return(0); } if (convType.IsExplicit() == firstImplicitFromType) { // secondType 可以隐式转换为 firstType。 return(1); } // firstType 可以隐式转换为 secondType。 return(-1); }