private Type ResolveExpressionCommonType(Type left, Type right, bool allowStringConcat, bool allowBothImplicit, bool allowObjectCoercion) { Require.NotNull(left, "left"); Require.NotNull(right, "right"); // No casting required. if (left == right) { return(left); } if (allowObjectCoercion) { if (left == typeof(object)) { return(right); } if (right == typeof(object)) { return(left); } } // Special cast for adding strings. if (allowStringConcat && (left == typeof(string) || right == typeof(string))) { return(typeof(string)); } // Can we cast implicitly? var leftTable = TypeUtil.GetImplicitCastingTable(left); var rightTable = TypeUtil.GetImplicitCastingTable(right); if (leftTable != null && rightTable != null) { // See whether one of the types appears in the other. foreach (var leftType in leftTable) { if (leftType == right) { return(leftType); } } foreach (var rightType in rightTable) { if (rightType == left) { return(rightType); } } // Otherwise, find the first common type. int lowest = int.MaxValue; for (int i = 0; i < leftTable.Count; i++) { for (int j = 0; j < rightTable.Count; j++) { if (leftTable[i] == rightTable[j]) { lowest = Math.Min(lowest, j); } } } if (lowest != int.MaxValue) { if ( allowBothImplicit || (IsAllowableImplicit(left, rightTable[lowest]) && IsAllowableImplicit(right, rightTable[lowest])) ) { return(rightTable[lowest]); } } } // We can't cast implicitly. throw new ExpressionsException("Cannot resolve expression type", ExpressionsExceptionType.TypeMismatch); }