Skip to content

Commit

Permalink
Rewrite switch statements as expressions (#865)
Browse files Browse the repository at this point in the history
  • Loading branch information
atifaziz authored Nov 4, 2022
1 parent 72d918e commit 42dbe20
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 125 deletions.
51 changes: 15 additions & 36 deletions MoreLinq.Test/FlattenTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,21 +325,13 @@ public void FlattenSelector()
}
};

var result = source.Flatten(obj =>
var result = source.Flatten(obj => obj switch
{
switch (obj)
{
case string:
return null;
case IEnumerable inner:
return inner;
case Series s:
return new object[] { s.Name, s.Attributes };
case Attribute a:
return a.Values;
default:
return null;
}
string => null,
IEnumerable inner => inner,
Series s => new object[] { s.Name, s.Attributes },
Attribute a => a.Values,
_ => null
});

var expectations = new object[] { "series1", 1, 2, 3, 4, "series2", 5, 6 };
Expand Down Expand Up @@ -368,17 +360,11 @@ public void FlattenSelectorFilteringOnlyIntegers()
4,
};

var result = source.Flatten(obj =>
var result = source.Flatten(obj => obj switch
{
switch (obj)
{
case int:
return null;
case IEnumerable inner:
return inner;
default:
return Enumerable.Empty<object>();
}
int => null,
IEnumerable inner => inner,
_ => Enumerable.Empty<object>()
});

var expectations = new object[] { 1, 2, 3, 4 };
Expand Down Expand Up @@ -406,19 +392,12 @@ public void FlattenSelectorWithTree()
)
);

var result = new [] { source }.Flatten(obj =>
var result = new[] { source }.Flatten(obj => obj switch
{
switch (obj)
{
case int:
return null;
case Tree<int> tree:
return new object[] { tree.Left, tree.Value, tree.Right };
case IEnumerable inner:
return inner;
default:
return Enumerable.Empty<object>();
}
int => null,
Tree<int> tree => new object[] { tree.Left, tree.Value, tree.Right },
IEnumerable inner => inner,
_ => Enumerable.Empty<object>()
});

var expectations = Enumerable.Range(1, 7);
Expand Down
15 changes: 7 additions & 8 deletions MoreLinq.Test/FromTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,14 @@ public void TestFromInvokesMethodsMultipleTimes(int numArgs)
int F3() { evals[2]++; return -2; }
int F4() { evals[3]++; return -2; }

IEnumerable<int> results;
switch (numArgs)
var results = numArgs switch
{
case 1: results = MoreEnumerable.From(F1); break;
case 2: results = MoreEnumerable.From(F1, F2); break;
case 3: results = MoreEnumerable.From(F1, F2, F3); break;
case 4: results = MoreEnumerable.From(F1, F2, F3, F4); break;
default: throw new ArgumentOutOfRangeException(nameof(numArgs));
}
1 => MoreEnumerable.From(F1),
2 => MoreEnumerable.From(F1, F2),
3 => MoreEnumerable.From(F1, F2, F3),
4 => MoreEnumerable.From(F1, F2, F3, F4),
_ => throw new ArgumentOutOfRangeException(nameof(numArgs))
};

results.Consume();
results.Consume();
Expand Down
17 changes: 6 additions & 11 deletions MoreLinq.Test/FullGroupJoinTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,12 @@ public void FullGroupPreservesOrder(OverloadCase overloadCase)
}
}

static IEnumerable<(int Key, IEnumerable<T> First, IEnumerable<T> Second)> FullGroupJoin<T>(OverloadCase overloadCase, IEnumerable<T> listA, IEnumerable<T> listB, Func<T, int> getKey)
{
switch (overloadCase)
static IEnumerable<(int Key, IEnumerable<T> First, IEnumerable<T> Second)> FullGroupJoin<T>(OverloadCase overloadCase, IEnumerable<T> listA, IEnumerable<T> listB, Func<T, int> getKey) =>
overloadCase switch
{
case CustomResult:
return listA.FullGroupJoin(listB, getKey, getKey, ValueTuple.Create, comparer: null);
case TupleResult:
return listA.FullGroupJoin(listB, getKey, getKey);
default:
throw new ArgumentOutOfRangeException(nameof(overloadCase));
}
}
CustomResult => listA.FullGroupJoin(listB, getKey, getKey, ValueTuple.Create, comparer: null),
TupleResult => listA.FullGroupJoin(listB, getKey, getKey),
_ => throw new ArgumentOutOfRangeException(nameof(overloadCase))
};
}
}
10 changes: 6 additions & 4 deletions MoreLinq.Test/NullArgumentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ static Type InstantiateType(TypeInfo typeParameter)
{
var constraints = typeParameter.GetGenericParameterConstraints();

if (constraints.Length == 0) return typeof (int);
if (constraints.Length == 1) return constraints.Single();

throw new NotImplementedException("NullArgumentTest.InstantiateType");
return constraints.Length switch
{
0 => typeof(int),
1 => constraints.Single(),
_ => throw new NotImplementedException("NullArgumentTest.InstantiateType")
};
}

static bool IsReferenceType(ParameterInfo parameter) =>
Expand Down
22 changes: 8 additions & 14 deletions MoreLinq.Test/TestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,15 @@ internal static IEnumerable<IEnumerable<T>> ArrangeCollectionTestCases<T>(this I

internal static IEnumerable<T> ToSourceKind<T>(this IEnumerable<T> input, SourceKind sourceKind)
{
switch (sourceKind)
return sourceKind switch
{
case SourceKind.Sequence:
return input.Select(x => x);
case SourceKind.BreakingList:
return new BreakingList<T>(input.ToList());
case SourceKind.BreakingReadOnlyList:
return new BreakingReadOnlyList<T>(input.ToList());
case SourceKind.BreakingCollection:
return new BreakingCollection<T>(input.ToList());
case SourceKind.BreakingReadOnlyCollection:
return new BreakingReadOnlyCollection<T>(input.ToList());
default:
throw new ArgumentException(null, nameof(sourceKind));
}
SourceKind.Sequence => input.Select(x => x),
SourceKind.BreakingList => new BreakingList<T>(input.ToList()),
SourceKind.BreakingReadOnlyList => new BreakingReadOnlyList<T>(input.ToList()),
SourceKind.BreakingCollection => new BreakingCollection<T>(input.ToList()),
SourceKind.BreakingReadOnlyCollection => new BreakingReadOnlyCollection<T>(input.ToList()),
_ => throw new ArgumentException(null, nameof(sourceKind))
};
}
}
}
11 changes: 7 additions & 4 deletions MoreLinq/Backsert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,15 @@ public static IEnumerable<T> Backsert<T>(this IEnumerable<T> first, IEnumerable<
{
if (first == null) throw new ArgumentNullException(nameof(first));
if (second == null) throw new ArgumentNullException(nameof(second));
if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Index cannot be negative.");

if (index == 0)
return first.Concat(second);
return index switch
{
< 0 => throw new ArgumentOutOfRangeException(nameof(index), "Index cannot be negative."),
0 => first.Concat(second),
_ => _()
};

return _(); IEnumerable<T> _()
IEnumerable<T> _()
{
using var e = first.CountDown(index, ValueTuple.Create).GetEnumerator();

Expand Down
11 changes: 7 additions & 4 deletions MoreLinq/Exclude.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ public static IEnumerable<T> Exclude<T>(this IEnumerable<T> sequence, int startI
{
if (sequence == null) throw new ArgumentNullException(nameof(sequence));
if (startIndex < 0) throw new ArgumentOutOfRangeException(nameof(startIndex));
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));

if (count == 0)
return sequence;
return count switch
{
< 0 => throw new ArgumentOutOfRangeException(nameof(count)),
0 => sequence,
_ => _()
};

return _(); IEnumerable<T> _()
IEnumerable<T> _()
{
var index = -1;
var endIndex = startIndex + count;
Expand Down
38 changes: 19 additions & 19 deletions MoreLinq/Fold.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,26 @@ static TResult FoldImpl<T, TResult>(IEnumerable<T> source, int count,
foreach (var e in AssertCountImpl(source.Index(), count, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

switch (count)
return count switch
{
case 1: return folder1 !(elements[0]);
case 2: return folder2 !(elements[0], elements[1]);
case 3: return folder3 !(elements[0], elements[1], elements[2]);
case 4: return folder4 !(elements[0], elements[1], elements[2], elements[3]);
case 5: return folder5 !(elements[0], elements[1], elements[2], elements[3], elements[4]);
case 6: return folder6 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
case 7: return folder7 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6]);
case 8: return folder8 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7]);
case 9: return folder9 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8]);
case 10: return folder10!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9]);
case 11: return folder11!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10]);
case 12: return folder12!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11]);
case 13: return folder13!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12]);
case 14: return folder14!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13]);
case 15: return folder15!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14]);
case 16: return folder16!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14], elements[15]);
default: throw new NotSupportedException();
}
1 => folder1 !(elements[0]),
2 => folder2 !(elements[0], elements[1]),
3 => folder3 !(elements[0], elements[1], elements[2]),
4 => folder4 !(elements[0], elements[1], elements[2], elements[3]),
5 => folder5 !(elements[0], elements[1], elements[2], elements[3], elements[4]),
6 => folder6 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]),
7 => folder7 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6]),
8 => folder8 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7]),
9 => folder9 !(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8]),
10 => folder10!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9]),
11 => folder11!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10]),
12 => folder12!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11]),
13 => folder13!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12]),
14 => folder14!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13]),
15 => folder15!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14]),
16 => folder16!(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14], elements[15]),
_ => throw new NotSupportedException()
};
}

static readonly Func<int, int, Exception> OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError;
Expand Down
18 changes: 9 additions & 9 deletions MoreLinq/MaxBy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,16 @@ IEnumerable<TSource> Extrema()
{
var item = e.Current;
var key = selector(item);
var comparison = comparer(key, extremaKey);
if (comparison > 0)
switch (comparer(key, extremaKey))
{
extrema.Restart(ref store);
extrema.Add(ref store, limit, item);
extremaKey = key;
}
else if (comparison == 0)
{
extrema.Add(ref store, limit, item);
case > 0:
extrema.Restart(ref store);
extrema.Add(ref store, limit, item);
extremaKey = key;
break;
case 0:
extrema.Add(ref store, limit, item);
break;
}
}

Expand Down
30 changes: 14 additions & 16 deletions MoreLinq/OrderedMerge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -300,23 +300,21 @@ IEnumerable<TResult> _(IComparer<TKey> comparer)
var key1 = firstKeySelector(element1);
var element2 = e2.Current;
var key2 = secondKeySelector(element2);
var comparison = comparer.Compare(key1, key2);

if (comparison < 0)
{
yield return firstSelector(element1);
gotFirst = e1.MoveNext();
}
else if (comparison > 0)
{
yield return secondSelector(element2);
gotSecond = e2.MoveNext();
}
else
switch (comparer.Compare(key1, key2))
{
yield return bothSelector(element1, element2);
gotFirst = e1.MoveNext();
gotSecond = e2.MoveNext();
case < 0:
yield return firstSelector(element1);
gotFirst = e1.MoveNext();
break;
case > 0:
yield return secondSelector(element2);
gotSecond = e2.MoveNext();
break;
default:
yield return bothSelector(element1, element2);
gotFirst = e1.MoveNext();
gotSecond = e2.MoveNext();
break;
}
}
else if (gotSecond)
Expand Down

0 comments on commit 42dbe20

Please sign in to comment.