public override Type EvaluateType() { // CASE WHEN's type depends on the most generous type from its branches // E.g. CASE WHEN <num> ELSE <string> END gives a string type var hasElseExpression = (ElseExpression != null); var distinctTypes = hasElseExpression ? CaseAlternatives.Select(n => n.EvaluateType()) .Union(new List <Type> { ElseExpression.EvaluateType() }) .Distinct() : CaseAlternatives.Select(n => n.EvaluateType()) .Distinct(); var anyNullable = distinctTypes.Any(t => TypeHelper.IsSystemNullableType(t)) // when Else statement is not provided resulting type becomes automatically nullable || !hasElseExpression; var distinctUnboxedTypes = distinctTypes .Select(t => TypeHelper.GetUnderlyingTypeIfNullable(t)).Distinct(); Type resultUnboxedType; if (distinctUnboxedTypes.Count() > 1) { resultUnboxedType = distinctUnboxedTypes.Aggregate((resType, nextType) => { Type resultedTypeRaw; if (!TypeCoersionTables.CoersionTableForValueType.TryGetValue((BinaryOperator.Plus, resType, nextType), out resultedTypeRaw)) { throw new TranspilerInternalErrorException($"Unexpected use of CASE WHEN operating between types {resType} and {nextType}"); } if (resultedTypeRaw == default(Type)) { throw new TranspilerNotSupportedException($"Case WHEN operating between types {resType} and {nextType}"); } return(resultedTypeRaw); }); } else { resultUnboxedType = distinctUnboxedTypes.First(); } return(anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultUnboxedType) : resultUnboxedType); }
public override string ToString() { return($"CaseExpr: Case {CaseAlternatives.ToString()} Else->{ElseExpression?.ToString() ?? "(None)"}"); }