Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite switch statements as expressions #865

Merged
merged 1 commit into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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