From cf55babce69e6cc601ba6696d80da8c3c5e54a96 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Sun, 25 Jun 2023 14:23:08 +0200 Subject: [PATCH] Revert removal of "Append" and "Prepend" This reverts commits: - Remove unused "Append"/"Prepend"supporting types: b9316f7f943cf1897f84a8fd4b9d6277265b82f9 - Remove "Append" and "Prepend": ca3a8e26b3d6401f7f3bcd7784f3468adf75c777 --- MoreLinq.Test/AppendTest.cs | 96 ++++++++++++++ MoreLinq.Test/PrependTest.cs | 95 +++++++++++++ MoreLinq/Append.cs | 46 +++++++ MoreLinq/Extensions.g.cs | 48 +++++++ MoreLinq/PendNode.cs | 125 ++++++++++++++++++ MoreLinq/Prepend.cs | 56 ++++++++ .../PublicAPI/net6.0/PublicAPI.Unshipped.txt | 6 +- .../netstandard2.0/PublicAPI.Unshipped.txt | 6 +- .../netstandard2.1/PublicAPI.Unshipped.txt | 6 +- MoreLinq/UnreachableException.cs | 58 ++++++++ README.md | 16 +-- 11 files changed, 534 insertions(+), 24 deletions(-) create mode 100644 MoreLinq.Test/AppendTest.cs create mode 100644 MoreLinq.Test/PrependTest.cs create mode 100644 MoreLinq/Append.cs create mode 100644 MoreLinq/PendNode.cs create mode 100644 MoreLinq/Prepend.cs create mode 100644 MoreLinq/UnreachableException.cs diff --git a/MoreLinq.Test/AppendTest.cs b/MoreLinq.Test/AppendTest.cs new file mode 100644 index 000000000..55ff31597 --- /dev/null +++ b/MoreLinq.Test/AppendTest.cs @@ -0,0 +1,96 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2008 Jonathan Skeet. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +#if !NET471_OR_GREATER && !NETSTANDARD1_6_OR_GREATER && !NETCOREAPP2_0_OR_GREATER + +namespace MoreLinq.Test +{ + using System.Collections.Generic; + using NUnit.Framework; + + [TestFixture] + public class AppendTest + { + #region Append with single head and tail sequence + [Test] + public void AppendWithNonEmptyHeadSequence() + { + var head = new[] { "first", "second" }; + var tail = "third"; + var whole = head.Append(tail); + whole.AssertSequenceEqual("first", "second", "third"); + } + + [Test] + public void AppendWithEmptyHeadSequence() + { + string[] head = { }; + var tail = "first"; + var whole = head.Append(tail); + whole.AssertSequenceEqual("first"); + } + + [Test] + public void AppendWithNullTail() + { + var head = new[] { "first", "second" }; + string? tail = null; + var whole = head.Append(tail); + whole.AssertSequenceEqual("first", "second", null); + } + + [Test] + public void AppendIsLazyInHeadSequence() + { + _ = new BreakingSequence().Append("tail"); + } + #endregion + + [TestCaseSource(nameof(ContactManySource))] + public void AppendMany(int[] head, int[] tail) + { + tail.Aggregate(head.AsEnumerable(), (xs, x) => xs.Append(x)) + .AssertSequenceEqual(head.Concat(tail)); + } + + public static IEnumerable ContactManySource => + from x in Enumerable.Range(0, 11) + from y in Enumerable.Range(1, 20 - x) + select new + { + Head = Enumerable.Range(1, x).ToArray(), + Tail = Enumerable.Range(x + 1, y).ToArray(), + } + into e + select new TestCaseData(e.Head, + e.Tail).SetName("Head = [" + string.Join(", ", e.Head) + "], " + + "Tail = [" + string.Join(", ", e.Tail) + "]"); + + [Test] + public void AppendWithSharedSource() + { + var first = new[] { 1 }.Append(2); + var second = first.Append(3).Append(4); + var third = first.Append(4).Append(8); + + second.AssertSequenceEqual(1, 2, 3, 4); + third.AssertSequenceEqual(1, 2, 4, 8); + } + } +} + +#endif diff --git a/MoreLinq.Test/PrependTest.cs b/MoreLinq.Test/PrependTest.cs new file mode 100644 index 000000000..3a4f938d1 --- /dev/null +++ b/MoreLinq.Test/PrependTest.cs @@ -0,0 +1,95 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2008 Jonathan Skeet. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +#if !NET471_OR_GREATER && !NETSTANDARD1_6_OR_GREATER && !NETCOREAPP2_0_OR_GREATER + +namespace MoreLinq.Test +{ + using System.Collections.Generic; + using NUnit.Framework; + using NUnit.Framework.Interfaces; + + [TestFixture] + public class PrependTest + { + [Test] + public void PrependWithNonEmptyTailSequence() + { + string[] tail = { "second", "third" }; + var head = "first"; + var whole = tail.Prepend(head); + whole.AssertSequenceEqual("first", "second", "third"); + } + + [Test] + public void PrependWithEmptyTailSequence() + { + string[] tail = { }; + var head = "first"; + var whole = tail.Prepend(head); + whole.AssertSequenceEqual("first"); + } + + [Test] + public void PrependWithNullHead() + { + string[] tail = { "second", "third" }; + string? head = null; + var whole = tail.Prepend(head); + whole.AssertSequenceEqual(null, "second", "third"); + } + + [Test] + public void PrependIsLazyInTailSequence() + { + _ = new BreakingSequence().Prepend("head"); + } + + [TestCaseSource(nameof(PrependManySource))] + public int[] PrependMany(int[] head, int[] tail) + { + return tail.Aggregate(head.AsEnumerable(), MoreEnumerable.Prepend).ToArray(); + } + + public static IEnumerable PrependManySource => + from x in Enumerable.Range(0, 11) + from y in Enumerable.Range(1, 11) + select new + { + Head = Enumerable.Range(0, y).Select(n => 0 - n).ToArray(), + Tail = Enumerable.Range(1, x).ToArray(), + } + into e + select new TestCaseData(e.Head, e.Tail) + .SetName("Head = [" + string.Join(", ", e.Head) + "], " + + "Tail = [" + string.Join(", ", e.Tail) + "]") + .Returns(e.Tail.Reverse().Concat(e.Head).ToArray()); + + [Test] + public void PrependWithSharedSource() + { + var first = new[] { 1 }.Prepend(2); + var second = first.Prepend(3).Prepend(4); + var third = first.Prepend(4).Prepend(8); + + second.AssertSequenceEqual(4, 3, 2, 1); + third.AssertSequenceEqual(8, 4, 2, 1); + } + } +} + +#endif diff --git a/MoreLinq/Append.cs b/MoreLinq/Append.cs new file mode 100644 index 000000000..3a02d376b --- /dev/null +++ b/MoreLinq/Append.cs @@ -0,0 +1,46 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2008 Jonathan Skeet. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns a sequence consisting of the head elements and the given tail element. + /// + /// Type of sequence + /// All elements of the head. Must not be null. + /// Tail element of the new sequence. + /// A sequence consisting of the head elements and the given tail element. + /// This operator uses deferred execution and streams its results. + +#if NET471_OR_GREATER || NETSTANDARD1_6_OR_GREATER || NETCOREAPP2_0_OR_GREATER + public static IEnumerable Append(IEnumerable head, T tail) +#else + public static IEnumerable Append(this IEnumerable head, T tail) +#endif + { + if (head == null) throw new ArgumentNullException(nameof(head)); + return head is PendNode node + ? node.Concat(tail) + : PendNode.WithSource(head).Concat(tail); + } + } +} diff --git a/MoreLinq/Extensions.g.cs b/MoreLinq/Extensions.g.cs index 4137ef772..b25c873fb 100644 --- a/MoreLinq/Extensions.g.cs +++ b/MoreLinq/Extensions.g.cs @@ -430,6 +430,25 @@ public static TResult AggregateRight(this IEnumer } + /// Append extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class AppendExtension + { + /// + /// Returns a sequence consisting of the head elements and the given tail element. + /// + /// Type of sequence + /// All elements of the head. Must not be null. + /// Tail element of the new sequence. + /// A sequence consisting of the head elements and the given tail element. + /// This operator uses deferred execution and streams its results. + + public static IEnumerable Append(this IEnumerable head, T tail) + => MoreEnumerable.Append(head, tail); + + } + /// Assert extension. [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] @@ -4540,6 +4559,35 @@ public static IEnumerable Pipe(this IEnumerable source, Action actio } + /// Prepend extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class PrependExtension + { + /// + /// Prepends a single value to a sequence. + /// + /// The type of the elements of . + /// The sequence to prepend to. + /// The value to prepend. + /// + /// Returns a sequence where a value is prepended to it. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// The result variable, when iterated over, will yield + /// 0, 1, 2 and 3, in turn. + + public static IEnumerable Prepend(this IEnumerable source, TSource value) + => MoreEnumerable.Prepend(source, value); + + } + /// PreScan extension. [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] diff --git a/MoreLinq/PendNode.cs b/MoreLinq/PendNode.cs new file mode 100644 index 000000000..2bf363863 --- /dev/null +++ b/MoreLinq/PendNode.cs @@ -0,0 +1,125 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2017 Atif Aziz. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections; + using System.Collections.Generic; + + /// + /// Prepend-Append node is a single linked-list of the discriminated union + /// of an item to prepend, an item to append and the source. + /// + + abstract class PendNode : IEnumerable + { + public static PendNode WithSource(IEnumerable source) => new Source(source); + + public PendNode Prepend(T item) => new Item(item, isPrepend: true , next: this); + public PendNode Concat(T item) => new Item(item, isPrepend: false, next: this); + + sealed class Item : PendNode + { + public T Value { get; } + public bool IsPrepend { get; } + public int ConcatCount { get; } + public PendNode Next { get; } + + public Item(T item, bool isPrepend, PendNode next) + { + if (next == null) throw new ArgumentNullException(nameof(next)); + + Value = item; + IsPrepend = isPrepend; + ConcatCount = next is Item nextItem + ? nextItem.ConcatCount + (isPrepend ? 0 : 1) + : 1; + Next = next; + } + } + + sealed class Source : PendNode + { + public IEnumerable Value { get; } + public Source(IEnumerable source) => Value = source; + } + + public IEnumerator GetEnumerator() + { + var i = 0; + T[]? concats = null; // Array for > 4 concatenations + var concat1 = default(T); // Slots for up to 4 concatenations + var concat2 = default(T); + var concat3 = default(T); + var concat4 = default(T); + + var current = this; + for (; current is Item item; current = item.Next) + { + if (item.IsPrepend) + { + yield return item.Value; + } + else + { + if (concats == null) + { + if (i == 0 && item.ConcatCount > 4) + { + concats = new T[item.ConcatCount]; + } + else + { + switch (i++) + { + case 0: concat1 = item.Value; break; + case 1: concat2 = item.Value; break; + case 2: concat3 = item.Value; break; + case 3: concat4 = item.Value; break; + default: throw new UnreachableException(); + } + continue; + } + } + + concats[i++] = item.Value; + } + } + + var source = (Source)current; + + foreach (var item in source.Value) + yield return item; + + if (concats == null) + { + if (i == 4) { yield return concat4!; i--; } + if (i == 3) { yield return concat3!; i--; } + if (i == 2) { yield return concat2!; i--; } + if (i == 1) { yield return concat1!; } + yield break; + } + + for (i--; i >= 0; i--) + yield return concats[i]; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + } +} diff --git a/MoreLinq/Prepend.cs b/MoreLinq/Prepend.cs new file mode 100644 index 000000000..fb82e8538 --- /dev/null +++ b/MoreLinq/Prepend.cs @@ -0,0 +1,56 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2009 Atif Aziz. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Prepends a single value to a sequence. + /// + /// The type of the elements of . + /// The sequence to prepend to. + /// The value to prepend. + /// + /// Returns a sequence where a value is prepended to it. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// The result variable, when iterated over, will yield + /// 0, 1, 2 and 3, in turn. + +#if NET471_OR_GREATER || NETSTANDARD1_6_OR_GREATER || NETCOREAPP2_0_OR_GREATER + public static IEnumerable Prepend(IEnumerable source, TSource value) +#else + public static IEnumerable Prepend(this IEnumerable source, TSource value) +#endif + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source is PendNode node + ? node.Prepend(value) + : PendNode.WithSource(source).Prepend(value); + } + } +} diff --git a/MoreLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt b/MoreLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt index 8efe28e0a..8959c7eec 100644 --- a/MoreLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt +++ b/MoreLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt @@ -1,8 +1,4 @@ #nullable enable -*REMOVED*MoreLinq.Extensions.AppendExtension -*REMOVED*MoreLinq.Extensions.PrependExtension -*REMOVED*static MoreLinq.Extensions.AppendExtension.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! -*REMOVED*static MoreLinq.Extensions.PrependExtension.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Concat(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! @@ -12,8 +8,10 @@ *REMOVED*static MoreLinq.MoreEnumerable.TakeLast(this System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.ToHashSet(this System.Collections.Generic.IEnumerable! source) -> System.Collections.Generic.HashSet! *REMOVED*static MoreLinq.MoreEnumerable.ToHashSet(this System.Collections.Generic.IEnumerable! source, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.HashSet! +static MoreLinq.MoreEnumerable.Append(System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.DistinctBy(System.Collections.Generic.IEnumerable! source, System.Func! keySelector) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.DistinctBy(System.Collections.Generic.IEnumerable! source, System.Func! keySelector, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable! +static MoreLinq.MoreEnumerable.Prepend(System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.SkipLast(System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.TakeLast(System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.ToHashSet(System.Collections.Generic.IEnumerable! source) -> System.Collections.Generic.HashSet! diff --git a/MoreLinq/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/MoreLinq/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 37e54326a..056e1801b 100644 --- a/MoreLinq/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/MoreLinq/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,8 +1,6 @@ #nullable enable -*REMOVED*MoreLinq.Extensions.AppendExtension -*REMOVED*MoreLinq.Extensions.PrependExtension -*REMOVED*static MoreLinq.Extensions.AppendExtension.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! -*REMOVED*static MoreLinq.Extensions.PrependExtension.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Concat(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! +static MoreLinq.MoreEnumerable.Append(System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! +static MoreLinq.MoreEnumerable.Prepend(System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! diff --git a/MoreLinq/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt b/MoreLinq/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt index ebb7ca31b..b025e7aed 100644 --- a/MoreLinq/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt +++ b/MoreLinq/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt @@ -1,8 +1,4 @@ #nullable enable -*REMOVED*MoreLinq.Extensions.AppendExtension -*REMOVED*MoreLinq.Extensions.PrependExtension -*REMOVED*static MoreLinq.Extensions.AppendExtension.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! -*REMOVED*static MoreLinq.Extensions.PrependExtension.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Append(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Concat(this System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.Prepend(this System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! @@ -10,6 +6,8 @@ *REMOVED*static MoreLinq.MoreEnumerable.TakeLast(this System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! *REMOVED*static MoreLinq.MoreEnumerable.ToHashSet(this System.Collections.Generic.IEnumerable! source) -> System.Collections.Generic.HashSet! *REMOVED*static MoreLinq.MoreEnumerable.ToHashSet(this System.Collections.Generic.IEnumerable! source, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.HashSet! +static MoreLinq.MoreEnumerable.Append(System.Collections.Generic.IEnumerable! head, T tail) -> System.Collections.Generic.IEnumerable! +static MoreLinq.MoreEnumerable.Prepend(System.Collections.Generic.IEnumerable! source, TSource value) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.SkipLast(System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.TakeLast(System.Collections.Generic.IEnumerable! source, int count) -> System.Collections.Generic.IEnumerable! static MoreLinq.MoreEnumerable.ToHashSet(System.Collections.Generic.IEnumerable! source) -> System.Collections.Generic.HashSet! diff --git a/MoreLinq/UnreachableException.cs b/MoreLinq/UnreachableException.cs new file mode 100644 index 000000000..80e4cf0eb --- /dev/null +++ b/MoreLinq/UnreachableException.cs @@ -0,0 +1,58 @@ +#region License and Terms +// The MIT License (MIT) +// +// Copyright (c) .NET Foundation and Contributors +// +// All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +#endregion + +#if !NET7_0_OR_GREATER + +namespace MoreLinq +{ + using System; + + // Source: https://github.com/dotnet/runtime/blob/v7.0.2/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs + + /// + /// Exception thrown when the program executes an instruction that was thought to be unreachable. + /// + +#if !NETSTANDARD1_0 + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif +#pragma warning disable CA1064 // Exceptions should be public + sealed class UnreachableException : Exception +#pragma warning restore CA1064 // Exceptions should be public + { + public UnreachableException() : + this(null) { } + + public UnreachableException(string? message) : + base(message, null) { } + + public UnreachableException(string? message, Exception? innerException) : + base(message ?? "The program executed an instruction that was thought to be unreachable.", + innerException) { } + } +} + +#endif // !NET7_0_OR_GREATER diff --git a/README.md b/README.md index b2f1c50ad..2c9962eda 100644 --- a/README.md +++ b/README.md @@ -103,14 +103,10 @@ This operator is the right-associative version of the Aggregate LINQ operator. This method has 3 overloads. -### ~~Append~~ +### Append Returns a sequence consisting of the head element and the given tail elements. -This extension was removed in version 4.0. Use [`Append`][linq-append] from .NET -instead that's been available since .NET Standard 1.6+, .NET Core 1.0+ and .NET -Framework 4.7.1+. - ### Assert Asserts that all elements of a sequence meet a given condition otherwise @@ -175,6 +171,8 @@ This extension was rendered obsolete in version 3.0 and eventually removed in version 4.0. Use [`Append`][linq-append] from .NET instead that's been available since .NET Standard 1.6+, .NET Core 1.0+ and .NET Framework 4.7.1+. +[linq-append]: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.append + ### Consume Completely consumes the given sequence. This method uses immediate execution, @@ -444,14 +442,10 @@ sequence Executes the given action on each element in the source sequence and yields it -### ~~Prepend~~ +### Prepend Prepends a single value to a sequence -This extension was removed in version 4.0. Use [`Prepend`][linq-prepend] from -.NET instead that's been available since .NET Standard 1.6+, .NET Core 1.0+ and -.NET Framework 4.7.1+. - ### PreScan Performs a pre-scan (exclusive prefix sum) on a sequence of elements @@ -788,5 +782,3 @@ This method has 2 overloads. [lookup]: https://docs.microsoft.com/en-us/dotnet/api/system.linq.lookup-2 [v2.1]: https://github.com/morelinq/MoreLINQ/releases/tag/v2.1.0 [v3.0]: https://github.com/morelinq/MoreLINQ/releases/tag/v3.0.0 -[linq-append]: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.append -[linq-prepend]: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.prepend