public static CSharpSwitchCase SwitchCase <T>(IEnumerable <T> testValues, IEnumerable <Expression> statements) { RequiresNotNull(testValues, nameof(testValues)); RequiresNotNull(statements, nameof(statements)); // NB: We don't check the body for Break statements; worst case we'll insert one at the end during Reduce. // Note that the semantics are nonetheless consistent with C#, i.e. no implicit fall-through. CheckValidSwitchType(typeof(T)); var testValuesList = testValues.Select(value => (object)value).ToReadOnly(); RequiresNotEmpty(testValuesList, nameof(testValues)); var uniqueTestValues = new HashSet <object>(); foreach (var value in testValuesList) { if (!uniqueTestValues.Add(value)) { throw Error.DuplicateTestValue(value.ToDebugString()); } } var statementsList = GetStatements(statements); return(new CSharpSwitchCase(testValuesList, statementsList)); }
public static CSharpSwitchCase SwitchCase(IEnumerable <object> testValues, IEnumerable <Expression> statements) { RequiresNotNull(testValues, nameof(testValues)); RequiresNotNull(statements, nameof(statements)); // NB: We don't check the body for Break statements; worst case we'll insert one at the end during Reduce. // Note that the semantics are nonetheless consistent with C#, i.e. no implicit fall-through. var testValuesList = testValues.ToReadOnly(); RequiresNotEmpty(testValuesList, nameof(testValues)); var testType = default(Type); var uniqueTestValues = new HashSet <object>(); foreach (var testValue in testValuesList) { if (!uniqueTestValues.Add(testValue)) { throw Error.DuplicateTestValue(testValue); } // NB: Null is fine; every valid governing type in C# has a nullable variant (trivial for string). if (testValue != null && testValue != SwitchCaseDefaultValue) { var testValueType = testValue.GetType(); if (testType == null) { testType = testValueType; } else { if (testType != testValueType) { throw Error.TestValuesShouldHaveConsistentType(); } } } } var statementsList = GetStatements(statements); return(new CSharpSwitchCase(testValuesList, statementsList)); }
public static SwitchCSharpStatement Switch(Expression switchValue, LabelTarget breakLabel, IEnumerable <ParameterExpression> variables, IEnumerable <CSharpSwitchCase> cases) { RequiresCanRead(switchValue, nameof(switchValue)); RequiresNotNull(breakLabel, nameof(breakLabel)); if (switchValue.Type == typeof(void)) { throw LinqError.ArgumentCannotBeOfTypeVoid(); } if (breakLabel.Type != typeof(void)) { throw Error.SwitchBreakLabelShouldBeVoid(); } var type = switchValue.Type; CheckValidSwitchType(type); var isNullable = type == typeof(string) || type.IsNullableType(); var nonNullType = type.GetNonNullableType(); // NB: Switch in C# can be empty, so less checks than LINQ here. Also no custom comparison method. var casesList = cases.ToReadOnly(); if (casesList.Count > 0) { var testValues = new HashSet <object>(); foreach (var @case in casesList) { RequiresNotNull(@case, nameof(cases)); foreach (var value in @case.TestValues) { if (!testValues.Add(value)) { throw Error.DuplicateTestValue(value.ToDebugString()); } if (value == null) { if (!isNullable) { throw Error.SwitchCantHaveNullCase(type); } } else if (value != SwitchCaseDefaultValue) { var valueType = value.GetType().GetNonNullableType(); if (valueType != nonNullType) { throw Error.SwitchCaseHasIncompatibleType(value.GetType(), type); } } } } } var variableList = CheckUniqueVariables(variables, nameof(variables)); return(new SwitchCSharpStatement(switchValue, breakLabel, variableList, casesList)); }