diff --git a/MoreLinq.Test/MaxByTest.cs b/MoreLinq.Test/MaxElementsByTest.cs similarity index 74% rename from MoreLinq.Test/MaxByTest.cs rename to MoreLinq.Test/MaxElementsByTest.cs index a2c8536f6..2ce037a85 100644 --- a/MoreLinq.Test/MaxByTest.cs +++ b/MoreLinq.Test/MaxElementsByTest.cs @@ -20,47 +20,47 @@ namespace MoreLinq.Test using System; using NUnit.Framework; - using static MoreLinq.Extensions.MaxByExtension; + using static MoreLinq.Extensions.MaxElementsByExtension; [TestFixture] - public class MaxByTest + public class MaxElementsByTest { [Test] - public void MaxByIsLazy() + public void MaxElementsByIsLazy() { - new BreakingSequence().MaxBy(BreakingFunc.Of()); + new BreakingSequence().MaxElementsBy(BreakingFunc.Of()); } [Test] - public void MaxByReturnsMaxima() + public void MaxElementsByReturnsMaxima() { Assert.AreEqual(new[] { "hello", "world" }, - SampleData.Strings.MaxBy(x => x.Length)); + SampleData.Strings.MaxElementsBy(x => x.Length)); } [Test] - public void MaxByNullComparer() + public void MaxElementsByNullComparer() { - Assert.AreEqual(SampleData.Strings.MaxBy(x => x.Length), - SampleData.Strings.MaxBy(x => x.Length, null)); + Assert.AreEqual(SampleData.Strings.MaxElementsBy(x => x.Length), + SampleData.Strings.MaxElementsBy(x => x.Length, null)); } [Test] - public void MaxByEmptySequence() + public void MaxElementsByEmptySequence() { - Assert.That(new string[0].MaxBy(x => x.Length), Is.Empty); + Assert.That(new string[0].MaxElementsBy(x => x.Length), Is.Empty); } [Test] - public void MaxByWithNaturalComparer() + public void MaxElementsByWithNaturalComparer() { - Assert.AreEqual(new[] { "az" }, SampleData.Strings.MaxBy(x => x[1])); + Assert.AreEqual(new[] { "az" }, SampleData.Strings.MaxElementsBy(x => x[1])); } [Test] - public void MaxByWithComparer() + public void MaxElementsByWithComparer() { - Assert.AreEqual(new[] { "aa" }, SampleData.Strings.MaxBy(x => x[1], Comparable.DescendingOrderComparer)); + Assert.AreEqual(new[] { "aa" }, SampleData.Strings.MaxElementsBy(x => x[1], Comparable.DescendingOrderComparer)); } public class First @@ -69,7 +69,7 @@ public class First public void ReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.First(maxima), Is.EqualTo("hello")); } @@ -77,7 +77,7 @@ public void ReturnsMaximum() public void WithComparerReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.First(maxima), Is.EqualTo("ax")); } @@ -86,7 +86,7 @@ public void WithEmptySourceThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.First(strings.MaxBy(s => s.Length))); + MoreEnumerable.First(strings.MaxElementsBy(s => s.Length))); } [Test] @@ -94,7 +94,7 @@ public void WithEmptySourceWithComparerThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.First(strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer))); + MoreEnumerable.First(strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer))); } } @@ -104,7 +104,7 @@ public class FirstOrDefault public void ReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.FirstOrDefault(maxima), Is.EqualTo("hello")); } @@ -112,7 +112,7 @@ public void ReturnsMaximum() public void WithComparerReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.FirstOrDefault(maxima), Is.EqualTo("ax")); } @@ -120,7 +120,7 @@ public void WithComparerReturnsMaximum() public void WithEmptySourceReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.FirstOrDefault(maxima), Is.Null); } @@ -128,7 +128,7 @@ public void WithEmptySourceReturnsDefault() public void WithEmptySourceWithComparerReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.FirstOrDefault(maxima), Is.Null); } } @@ -139,7 +139,7 @@ public class Last public void ReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.Last(maxima), Is.EqualTo("world")); } @@ -147,7 +147,7 @@ public void ReturnsMaximum() public void WithComparerReturnsMaximumPerComparer() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.Last(maxima), Is.EqualTo("az")); } @@ -156,7 +156,7 @@ public void WithEmptySourceThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.Last(strings.MaxBy(s => s.Length))); + MoreEnumerable.Last(strings.MaxElementsBy(s => s.Length))); } [Test] @@ -164,7 +164,7 @@ public void WithEmptySourceWithComparerThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.Last(strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer))); + MoreEnumerable.Last(strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer))); } } @@ -174,7 +174,7 @@ public class LastOrDefault public void ReturnsMaximum() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.LastOrDefault(maxima), Is.EqualTo("world")); } @@ -182,7 +182,7 @@ public void ReturnsMaximum() public void WithComparerReturnsMaximumPerComparer() { using var strings = SampleData.Strings.AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.LastOrDefault(maxima), Is.EqualTo("az")); } @@ -190,7 +190,7 @@ public void WithComparerReturnsMaximumPerComparer() public void WithEmptySourceReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length); + var maxima = strings.MaxElementsBy(s => s.Length); Assert.That(MoreEnumerable.LastOrDefault(maxima), Is.Null); } @@ -198,7 +198,7 @@ public void WithEmptySourceReturnsDefault() public void WithEmptySourceWithComparerReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var maxima = strings.MaxBy(s => s.Length, Comparable.DescendingOrderComparer); + var maxima = strings.MaxElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.LastOrDefault(maxima), Is.Null); } } @@ -212,7 +212,7 @@ public class Take public string[] ReturnsMaxima(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MaxBy(s => s.Length).Take(count).ToArray(); + return strings.MaxElementsBy(s => s.Length).Take(count).ToArray(); } [TestCase(0, 0, ExpectedResult = new string[0] )] @@ -226,7 +226,7 @@ public string[] ReturnsMaxima(int count) public string[] WithComparerReturnsMaximaPerComparer(int count, int index) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MaxBy(s => s[index], Comparable.DescendingOrderComparer) + return strings.MaxElementsBy(s => s[index], Comparable.DescendingOrderComparer) .Take(count) .ToArray(); } @@ -241,7 +241,7 @@ public class TakeLast public string[] TakeLastReturnsMaxima(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MaxBy(s => s.Length).TakeLast(count).ToArray(); + return strings.MaxElementsBy(s => s.Length).TakeLast(count).ToArray(); } [TestCase(0, 0, ExpectedResult = new string[0] )] @@ -255,7 +255,7 @@ public string[] TakeLastReturnsMaxima(int count) public string[] WithComparerReturnsMaximaPerComparer(int count, int index) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MaxBy(s => s[index], Comparable.DescendingOrderComparer) + return strings.MaxElementsBy(s => s[index], Comparable.DescendingOrderComparer) .TakeLast(count) .ToArray(); } @@ -270,9 +270,12 @@ namespace Linq public static partial class BuildTest { - public static void MaxByCanBuildWithSystemLinq() + public static void MaxElementsByCanBuildWithSystemLinq() { +#pragma warning disable CS0618 new int[0].MaxBy(x => 1); + new int[0].MaxElementsBy(x => 1); +#pragma warning restore CS0618 } } } diff --git a/MoreLinq.Test/MinByTest.cs b/MoreLinq.Test/MinElementsByTest.cs similarity index 74% rename from MoreLinq.Test/MinByTest.cs rename to MoreLinq.Test/MinElementsByTest.cs index 080f28905..dbc21a9b2 100644 --- a/MoreLinq.Test/MinByTest.cs +++ b/MoreLinq.Test/MinElementsByTest.cs @@ -20,47 +20,47 @@ namespace MoreLinq.Test using System; using NUnit.Framework; - using static MoreLinq.Extensions.MinByExtension; + using static MoreLinq.Extensions.MinElementsByExtension; [TestFixture] - public class MinByTest + public class MinElementsByTest { [Test] - public void MinByIsLazy() + public void MinElementsByIsLazy() { - new BreakingSequence().MinBy(BreakingFunc.Of()); + new BreakingSequence().MinElementsBy(BreakingFunc.Of()); } [Test] - public void MinByReturnsMinima() + public void MinElementsByReturnsMinima() { Assert.AreEqual(new[] { "ax", "aa", "ab", "ay", "az" }, - SampleData.Strings.MinBy(x => x.Length)); + SampleData.Strings.MinElementsBy(x => x.Length)); } [Test] - public void MinByNullComparer() + public void MinElementsByNullComparer() { - Assert.AreEqual(SampleData.Strings.MinBy(x => x.Length), - SampleData.Strings.MinBy(x => x.Length, null)); + Assert.AreEqual(SampleData.Strings.MinElementsBy(x => x.Length), + SampleData.Strings.MinElementsBy(x => x.Length, null)); } [Test] - public void MinByEmptySequence() + public void MinElementsByEmptySequence() { - Assert.That(new string[0].MinBy(x => x.Length), Is.Empty); + Assert.That(new string[0].MinElementsBy(x => x.Length), Is.Empty); } [Test] - public void MinByWithNaturalComparer() + public void MinElementsByWithNaturalComparer() { - Assert.AreEqual(new[] { "aa" }, SampleData.Strings.MinBy(x => x[1])); + Assert.AreEqual(new[] { "aa" }, SampleData.Strings.MinElementsBy(x => x[1])); } [Test] - public void MinByWithComparer() + public void MinElementsByWithComparer() { - Assert.AreEqual(new[] { "az" }, SampleData.Strings.MinBy(x => x[1], Comparable.DescendingOrderComparer)); + Assert.AreEqual(new[] { "az" }, SampleData.Strings.MinElementsBy(x => x[1], Comparable.DescendingOrderComparer)); } public class First @@ -69,7 +69,7 @@ public class First public void ReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = MoreEnumerable.First(strings.MinBy(s => s.Length)); + var minima = MoreEnumerable.First(strings.MinElementsBy(s => s.Length)); Assert.That(minima, Is.EqualTo("ax")); } @@ -77,7 +77,7 @@ public void ReturnsMinimum() public void WithComparerReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.First(minima), Is.EqualTo("hello")); } @@ -86,7 +86,7 @@ public void WithEmptySourceThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.First(strings.MinBy(s => s.Length))); + MoreEnumerable.First(strings.MinElementsBy(s => s.Length))); } [Test] @@ -94,7 +94,7 @@ public void WithEmptySourceWithComparerThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.First(strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer))); + MoreEnumerable.First(strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer))); } } @@ -104,7 +104,7 @@ public class FirstOrDefault public void ReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length); + var minima = strings.MinElementsBy(s => s.Length); Assert.That(MoreEnumerable.FirstOrDefault(minima), Is.EqualTo("ax")); } @@ -112,7 +112,7 @@ public void ReturnsMinimum() public void WithComparerReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.FirstOrDefault(minima), Is.EqualTo("hello")); } @@ -120,7 +120,7 @@ public void WithComparerReturnsMinimum() public void WithEmptySourceReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var minima = strings.MinBy(s => s.Length); + var minima = strings.MinElementsBy(s => s.Length); Assert.That(MoreEnumerable.FirstOrDefault(minima), Is.Null); } @@ -128,7 +128,7 @@ public void WithEmptySourceReturnsDefault() public void WithEmptySourceWithComparerReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.FirstOrDefault(minima), Is.Null); } } @@ -139,7 +139,7 @@ public class Last public void ReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length); + var minima = strings.MinElementsBy(s => s.Length); Assert.That(MoreEnumerable.Last(minima), Is.EqualTo("az")); } @@ -147,7 +147,7 @@ public void ReturnsMinimum() public void WithComparerReturnsMinimumPerComparer() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.Last(minima), Is.EqualTo("world")); } @@ -156,7 +156,7 @@ public void WithEmptySourceThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.Last(strings.MinBy(s => s.Length))); + MoreEnumerable.Last(strings.MinElementsBy(s => s.Length))); } [Test] @@ -164,7 +164,7 @@ public void WithEmptySourceWithComparerThrows() { using var strings = Enumerable.Empty().AsTestingSequence(); Assert.Throws(() => - MoreEnumerable.Last(strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer))); + MoreEnumerable.Last(strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer))); } } @@ -174,7 +174,7 @@ public class LastOrDefault public void ReturnsMinimum() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length); + var minima = strings.MinElementsBy(s => s.Length); Assert.That(MoreEnumerable.LastOrDefault(minima), Is.EqualTo("az")); } @@ -182,7 +182,7 @@ public void ReturnsMinimum() public void WithComparerReturnsMinimumPerComparer() { using var strings = SampleData.Strings.AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.LastOrDefault(minima), Is.EqualTo("world")); } @@ -190,7 +190,7 @@ public void WithComparerReturnsMinimumPerComparer() public void WithEmptySourceReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var minima = strings.MinBy(s => s.Length); + var minima = strings.MinElementsBy(s => s.Length); Assert.That(MoreEnumerable.LastOrDefault(minima), Is.Null); } @@ -198,7 +198,7 @@ public void WithEmptySourceReturnsDefault() public void WithEmptySourceWithComparerReturnsDefault() { using var strings = Enumerable.Empty().AsTestingSequence(); - var minima = strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer); + var minima = strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer); Assert.That(MoreEnumerable.LastOrDefault(minima), Is.Null); } } @@ -215,7 +215,7 @@ public class Take public string[] ReturnsMinima(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MinBy(s => s.Length).Take(count).ToArray(); + return strings.MinElementsBy(s => s.Length).Take(count).ToArray(); } [TestCase(0, ExpectedResult = new string[0] )] @@ -225,7 +225,7 @@ public string[] ReturnsMinima(int count) public string[] WithComparerReturnsMinimaPerComparer(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer) + return strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer) .Take(count) .ToArray(); } @@ -243,7 +243,7 @@ public class TakeLast public string[] ReturnsMinima(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MinBy(s => s.Length).TakeLast(count).ToArray(); + return strings.MinElementsBy(s => s.Length).TakeLast(count).ToArray(); } [TestCase(0, ExpectedResult = new string[0] )] @@ -253,7 +253,7 @@ public string[] ReturnsMinima(int count) public string[] WithComparerReturnsMinimaPerComparer(int count) { using var strings = SampleData.Strings.AsTestingSequence(); - return strings.MinBy(s => s.Length, Comparable.DescendingOrderComparer) + return strings.MinElementsBy(s => s.Length, Comparable.DescendingOrderComparer) .TakeLast(count) .ToArray(); } @@ -268,9 +268,13 @@ namespace Linq public static partial class BuildTest { - public static void MinByCanBuildWithSystemLinq() + public static void MinElementsByCanBuildWithSystemLinq() { +#pragma warning disable CS0618 new int[0].MinBy(x => 1); + new int[0].MinElementsBy(x => 1); +#pragma warning restore CS0618 } + } } diff --git a/MoreLinq/Extensions.g.cs b/MoreLinq/Extensions.g.cs index 1f183518e..4f7413482 100644 --- a/MoreLinq/Extensions.g.cs +++ b/MoreLinq/Extensions.g.cs @@ -3330,7 +3330,7 @@ public static partial class MaxByExtension public static IExtremaEnumerable MaxBy(this IEnumerable source, Func selector) - => MoreEnumerable.MaxBy(source, selector); + => MoreEnumerable.MaxElementsBy(source, selector); /// /// Returns the maximal elements of the given sequence, based on @@ -3351,7 +3351,56 @@ public static IExtremaEnumerable MaxBy(this IEnumerable< public static IExtremaEnumerable MaxBy(this IEnumerable source, Func selector, IComparer? comparer) - => MoreEnumerable.MaxBy(source, selector, comparer); + => MoreEnumerable.MaxElementsBy(source, selector, comparer); + + } + + /// MaxElementsBy extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class MaxElementsByExtension + { + + /// + /// Returns the maximal elements of the given sequence, based on + /// the given projection. + /// + /// + /// This overload uses the default comparer for the projected type. + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The sequence of maximal elements, according to the projection. + /// or is null + + public static IExtremaEnumerable MaxElementsBy(this IEnumerable source, + Func selector) + => MoreEnumerable.MaxElementsBy(source, selector); + + /// + /// Returns the maximal elements of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// Comparer to use to compare projected values + /// The sequence of maximal elements, according to the projection. + /// , + /// or is null + + public static IExtremaEnumerable MaxElementsBy(this IEnumerable source, + Func selector, IComparer? comparer) + => MoreEnumerable.MaxElementsBy(source, selector, comparer); } @@ -3378,7 +3427,7 @@ public static partial class MinByExtension public static IExtremaEnumerable MinBy(this IEnumerable source, Func selector) - => MoreEnumerable.MinBy(source, selector); + => MoreEnumerable.MinElementsBy(source, selector); /// /// Returns the minimal elements of the given sequence, based on @@ -3399,7 +3448,55 @@ public static IExtremaEnumerable MinBy(this IEnumerable< public static IExtremaEnumerable MinBy(this IEnumerable source, Func selector, IComparer? comparer) - => MoreEnumerable.MinBy(source, selector, comparer); + => MoreEnumerable.MinElementsBy(source, selector, comparer); + + } + + /// MinElementsBy extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class MinElementsByExtension + { + /// + /// Returns the minimal elements of the given sequence, based on + /// the given projection. + /// + /// + /// This overload uses the default comparer for the projected type. + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The sequence of minimal elements, according to the projection. + /// or is null + + public static IExtremaEnumerable MinElementsBy(this IEnumerable source, + Func selector) + => MoreEnumerable.MinElementsBy(source, selector); + + /// + /// Returns the minimal elements of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// Comparer to use to compare projected values + /// The sequence of minimal elements, according to the projection. + /// , + /// or is null + + public static IExtremaEnumerable MinElementsBy(this IEnumerable source, + Func selector, IComparer? comparer) + => MoreEnumerable.MinElementsBy(source, selector, comparer); } diff --git a/MoreLinq/MaxBy.cs b/MoreLinq/MaxBy.cs index 4ce8877bd..43d21f393 100644 --- a/MoreLinq/MaxBy.cs +++ b/MoreLinq/MaxBy.cs @@ -22,154 +22,10 @@ namespace MoreLinq using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; - - /// - /// Exposes the enumerator, which supports iteration over a sequence of - /// some extremum property (maximum or minimum) of a specified type. - /// - /// The type of objects to enumerate. - - public interface IExtremaEnumerable : IEnumerable - { - /// - /// Returns a specified number of contiguous elements from the start of - /// the sequence. - /// - /// The number of elements to return. - /// - /// An that contains the specified number - /// of elements from the start of the input sequence. - /// - - IEnumerable Take(int count); - - /// - /// Returns a specified number of contiguous elements at the end of the - /// sequence. - /// - /// The number of elements to return. - /// - /// An that contains the specified number - /// of elements at the end of the input sequence. - /// - - IEnumerable TakeLast(int count); - } + using System.Runtime.CompilerServices; static partial class MoreEnumerable { - /// - /// Returns the first element of a sequence. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// The input sequence is empty. - /// - /// The first element of the input sequence. - /// - - public static T First(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.Take(1).AsEnumerable().First(); - } - - /// - /// Returns the first element of a sequence, or a default value if the - /// sequence contains no elements. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// Default value of type if source is empty; - /// otherwise, the first element in source. - /// - - [return: MaybeNull] - public static T FirstOrDefault(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.Take(1).AsEnumerable().FirstOrDefault(); - } - - /// - /// Returns the last element of a sequence. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// The input sequence is empty. - /// - /// The last element of the input sequence. - /// - - public static T Last(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.TakeLast(1).AsEnumerable().Last(); - } - - /// - /// Returns the last element of a sequence, or a default value if the - /// sequence contains no elements. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// Default value of type if source is empty; - /// otherwise, the last element in source. - /// - - [return: MaybeNull] - public static T LastOrDefault(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.TakeLast(1).AsEnumerable().LastOrDefault(); - } - - /// - /// Returns the only element of a sequence, and throws an exception if - /// there is not exactly one element in the sequence. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// The input sequence contains more than one element. - /// - /// The single element of the input sequence. - /// - - public static T Single(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.Take(2).AsEnumerable().Single(); - } - - /// - /// Returns the only element of a sequence, or a default value if the - /// sequence is empty; this method throws an exception if there is more - /// than one element in the sequence. - /// - /// - /// The type of the elements of . - /// The input sequence. - /// - /// The single element of the input sequence, or default value of type - /// if the sequence contains no elements. - /// - - [return: MaybeNull] - public static T SingleOrDefault(this IExtremaEnumerable source) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - return source.Take(2).AsEnumerable().SingleOrDefault(); - } /// /// Returns the maximal elements of the given sequence, based on @@ -187,16 +43,17 @@ public static T SingleOrDefault(this IExtremaEnumerable source) /// The sequence of maximal elements, according to the projection. /// or is null + [MethodImpl(MethodImplOptions.AggressiveInlining)] #if NET6_0_OR_GREATER + [Obsolete("MaxBy() conflicts with new .NET Core method. Use MaxElementsBy() instead.")] public static IExtremaEnumerable MaxBy(IEnumerable source, Func selector) #else + [Obsolete("MaxBy() conflicts with new .NET Core method. Use MaxElementsBy() instead.")] public static IExtremaEnumerable MaxBy(this IEnumerable source, Func selector) #endif - { - return MaxBy(source, selector, null); - } + => MaxElementsBy(source, selector); /// /// Returns the maximal elements of the given sequence, based on @@ -215,164 +72,16 @@ public static IExtremaEnumerable MaxBy(this IEnumerable< /// , /// or is null + [MethodImpl(MethodImplOptions.AggressiveInlining)] #if NET6_0_OR_GREATER + [Obsolete("MaxBy() conflicts with new .NET Core method. Use MaxElementsBy() instead.")] public static IExtremaEnumerable MaxBy(IEnumerable source, Func selector, IComparer? comparer) #else + [Obsolete("MaxBy() conflicts with new .NET Core method. Use MaxElementsBy() instead.")] public static IExtremaEnumerable MaxBy(this IEnumerable source, Func selector, IComparer? comparer) #endif - { - if (source == null) throw new ArgumentNullException(nameof(source)); - if (selector == null) throw new ArgumentNullException(nameof(selector)); - - comparer ??= Comparer.Default; - return new ExtremaEnumerable(source, selector, (x, y) => comparer.Compare(x, y)); - } - - sealed class ExtremaEnumerable : IExtremaEnumerable - { - readonly IEnumerable _source; - readonly Func _selector; - readonly Func _comparer; - - public ExtremaEnumerable(IEnumerable source, Func selector, Func comparer) - { - _source = source; - _selector = selector; - _comparer = comparer; - } - - public IEnumerator GetEnumerator() => - ExtremaBy(_source, Extrema.First, null, _selector, _comparer).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => - GetEnumerator(); - - public IEnumerable Take(int count) => - count switch - { - 0 => Enumerable.Empty(), - 1 => ExtremaBy(_source, Extremum.First, 1, _selector, _comparer), - _ => ExtremaBy(_source, Extrema.First, count, _selector, _comparer) - }; - - public IEnumerable TakeLast(int count) => - count switch - { - 0 => Enumerable.Empty(), - 1 => ExtremaBy(_source, Extremum.Last, 1, _selector, _comparer), - _ => ExtremaBy(_source, Extrema.Last, count, _selector, _comparer) - }; - - static class Extrema - { - public static readonly Extrema?, T> First = new FirstExtrema(); - public static readonly Extrema?, T> Last = new LastExtrema(); - - sealed class FirstExtrema : Extrema?, T> - { - public override List? New() => null; - public override void Restart(ref List? store) => store = null; - public override IEnumerable GetEnumerable(List? store) => store ?? Enumerable.Empty(); - - public override void Add(ref List? store, int? limit, T item) - { - if (limit == null || store is null || store.Count < limit) - (store ??= new List()).Add(item); - } - } - - sealed class LastExtrema : Extrema?, T> - { - public override Queue? New() => null; - public override void Restart(ref Queue? store) => store = null; - public override IEnumerable GetEnumerable(Queue? store) => store ?? Enumerable.Empty(); - - public override void Add(ref Queue? store, int? limit, T item) - { - if (limit is { } n && store is { } queue && queue.Count == n) - queue.Dequeue(); - (store ??= new Queue()).Enqueue(item); - } - } - } - - sealed class Extremum : Extrema<(bool, T), T> - { - public static readonly Extrema<(bool, T), T> First = new Extremum(false); - public static readonly Extrema<(bool, T), T> Last = new Extremum(true); - - readonly bool _poppable; - Extremum(bool poppable) => _poppable = poppable; - - public override (bool, T) New() => default; - public override void Restart(ref (bool, T) store) => store = default; - - public override IEnumerable GetEnumerable((bool, T) store) => - store is (true, var item) ? Enumerable.Repeat(item, 1) : Enumerable.Empty(); - - public override void Add(ref (bool, T) store, int? limit, T item) - { - if (!_poppable && store is (true, _)) - return; - store = (true, item); - } - } - } - - // > In mathematical analysis, the maxima and minima (the respective - // > plurals of maximum and minimum) of a function, known collectively - // > as extrema (the plural of extremum), ... - // > - // > - https://en.wikipedia.org/wiki/Maxima_and_minima - - static IEnumerable ExtremaBy( - this IEnumerable source, - Extrema extrema, int? limit, - Func selector, Func comparer) - { - foreach (var item in Extrema()) - yield return item; - - IEnumerable Extrema() - { - using var e = source.GetEnumerator(); - - if (!e.MoveNext()) - return new List(); - - var store = extrema.New(); - extrema.Add(ref store, limit, e.Current); - var extremaKey = selector(e.Current); - - while (e.MoveNext()) - { - var item = e.Current; - var key = selector(item); - var comparison = comparer(key, extremaKey); - if (comparison > 0) - { - extrema.Restart(ref store); - extrema.Add(ref store, limit, item); - extremaKey = key; - } - else if (comparison == 0) - { - extrema.Add(ref store, limit, item); - } - } - - return extrema.GetEnumerable(store); - } - } - - abstract class Extrema - { - public abstract TStore New(); - public abstract void Restart(ref TStore store); - public abstract IEnumerable GetEnumerable(TStore store); - public abstract void Add(ref TStore store, int? limit, T item); - } + => MaxElementsBy(source, selector, comparer); } } diff --git a/MoreLinq/MaxElementsBy.cs b/MoreLinq/MaxElementsBy.cs new file mode 100644 index 000000000..1b594bdb3 --- /dev/null +++ b/MoreLinq/MaxElementsBy.cs @@ -0,0 +1,368 @@ +#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; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + + /// + /// Exposes the enumerator, which supports iteration over a sequence of + /// some extremum property (maximum or minimum) of a specified type. + /// + /// The type of objects to enumerate. + + public interface IExtremaEnumerable : IEnumerable + { + /// + /// Returns a specified number of contiguous elements from the start of + /// the sequence. + /// + /// The number of elements to return. + /// + /// An that contains the specified number + /// of elements from the start of the input sequence. + /// + + IEnumerable Take(int count); + + /// + /// Returns a specified number of contiguous elements at the end of the + /// sequence. + /// + /// The number of elements to return. + /// + /// An that contains the specified number + /// of elements at the end of the input sequence. + /// + + IEnumerable TakeLast(int count); + } + + static partial class MoreEnumerable + { + /// + /// Returns the first element of a sequence. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// The input sequence is empty. + /// + /// The first element of the input sequence. + /// + + public static T First(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.Take(1).AsEnumerable().First(); + } + + /// + /// Returns the first element of a sequence, or a default value if the + /// sequence contains no elements. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// Default value of type if source is empty; + /// otherwise, the first element in source. + /// + + [return: MaybeNull] + public static T FirstOrDefault(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.Take(1).AsEnumerable().FirstOrDefault(); + } + + /// + /// Returns the last element of a sequence. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// The input sequence is empty. + /// + /// The last element of the input sequence. + /// + + public static T Last(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.TakeLast(1).AsEnumerable().Last(); + } + + /// + /// Returns the last element of a sequence, or a default value if the + /// sequence contains no elements. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// Default value of type if source is empty; + /// otherwise, the last element in source. + /// + + [return: MaybeNull] + public static T LastOrDefault(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.TakeLast(1).AsEnumerable().LastOrDefault(); + } + + /// + /// Returns the only element of a sequence, and throws an exception if + /// there is not exactly one element in the sequence. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// The input sequence contains more than one element. + /// + /// The single element of the input sequence. + /// + + public static T Single(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.Take(2).AsEnumerable().Single(); + } + + /// + /// Returns the only element of a sequence, or a default value if the + /// sequence is empty; this method throws an exception if there is more + /// than one element in the sequence. + /// + /// + /// The type of the elements of . + /// The input sequence. + /// + /// The single element of the input sequence, or default value of type + /// if the sequence contains no elements. + /// + + [return: MaybeNull] + public static T SingleOrDefault(this IExtremaEnumerable source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + return source.Take(2).AsEnumerable().SingleOrDefault(); + } + + /// + /// Returns the maximal elements of the given sequence, based on + /// the given projection. + /// + /// + /// This overload uses the default comparer for the projected type. + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The sequence of maximal elements, according to the projection. + /// or is null + + public static IExtremaEnumerable MaxElementsBy(this IEnumerable source, + Func selector) + { + return MaxElementsBy(source, selector, null); + } + + /// + /// Returns the maximal elements of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// Comparer to use to compare projected values + /// The sequence of maximal elements, according to the projection. + /// , + /// or is null + + public static IExtremaEnumerable MaxElementsBy(this IEnumerable source, + Func selector, IComparer? comparer) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (selector == null) throw new ArgumentNullException(nameof(selector)); + + comparer ??= Comparer.Default; + return new ExtremaEnumerable(source, selector, (x, y) => comparer.Compare(x, y)); + } + + sealed class ExtremaEnumerable : IExtremaEnumerable + { + readonly IEnumerable _source; + readonly Func _selector; + readonly Func _comparer; + + public ExtremaEnumerable(IEnumerable source, Func selector, Func comparer) + { + _source = source; + _selector = selector; + _comparer = comparer; + } + + public IEnumerator GetEnumerator() => + ExtremaBy(_source, Extrema.First, null, _selector, _comparer).GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => + GetEnumerator(); + + public IEnumerable Take(int count) => + count switch + { + 0 => Enumerable.Empty(), + 1 => ExtremaBy(_source, Extremum.First, 1, _selector, _comparer), + _ => ExtremaBy(_source, Extrema.First, count, _selector, _comparer) + }; + + public IEnumerable TakeLast(int count) => + count switch + { + 0 => Enumerable.Empty(), + 1 => ExtremaBy(_source, Extremum.Last, 1, _selector, _comparer), + _ => ExtremaBy(_source, Extrema.Last, count, _selector, _comparer) + }; + + static class Extrema + { + public static readonly Extrema?, T> First = new FirstExtrema(); + public static readonly Extrema?, T> Last = new LastExtrema(); + + sealed class FirstExtrema : Extrema?, T> + { + public override List? New() => null; + public override void Restart(ref List? store) => store = null; + public override IEnumerable GetEnumerable(List? store) => store ?? Enumerable.Empty(); + + public override void Add(ref List? store, int? limit, T item) + { + if (limit == null || store is null || store.Count < limit) + (store ??= new List()).Add(item); + } + } + + sealed class LastExtrema : Extrema?, T> + { + public override Queue? New() => null; + public override void Restart(ref Queue? store) => store = null; + public override IEnumerable GetEnumerable(Queue? store) => store ?? Enumerable.Empty(); + + public override void Add(ref Queue? store, int? limit, T item) + { + if (limit is { } n && store is { } queue && queue.Count == n) + queue.Dequeue(); + (store ??= new Queue()).Enqueue(item); + } + } + } + + sealed class Extremum : Extrema<(bool, T), T> + { + public static readonly Extrema<(bool, T), T> First = new Extremum(false); + public static readonly Extrema<(bool, T), T> Last = new Extremum(true); + + readonly bool _poppable; + Extremum(bool poppable) => _poppable = poppable; + + public override (bool, T) New() => default; + public override void Restart(ref (bool, T) store) => store = default; + + public override IEnumerable GetEnumerable((bool, T) store) => + store is (true, var item) ? Enumerable.Repeat(item, 1) : Enumerable.Empty(); + + public override void Add(ref (bool, T) store, int? limit, T item) + { + if (!_poppable && store is (true, _)) + return; + store = (true, item); + } + } + } + + // > In mathematical analysis, the maxima and minima (the respective + // > plurals of maximum and minimum) of a function, known collectively + // > as extrema (the plural of extremum), ... + // > + // > - https://en.wikipedia.org/wiki/Maxima_and_minima + + static IEnumerable ExtremaBy( + this IEnumerable source, + Extrema extrema, int? limit, + Func selector, Func comparer) + { + foreach (var item in Extrema()) + yield return item; + + IEnumerable Extrema() + { + using var e = source.GetEnumerator(); + + if (!e.MoveNext()) + return new List(); + + var store = extrema.New(); + extrema.Add(ref store, limit, e.Current); + var extremaKey = selector(e.Current); + + while (e.MoveNext()) + { + var item = e.Current; + var key = selector(item); + var comparison = comparer(key, extremaKey); + if (comparison > 0) + { + extrema.Restart(ref store); + extrema.Add(ref store, limit, item); + extremaKey = key; + } + else if (comparison == 0) + { + extrema.Add(ref store, limit, item); + } + } + + return extrema.GetEnumerable(store); + } + } + + abstract class Extrema + { + public abstract TStore New(); + public abstract void Restart(ref TStore store); + public abstract IEnumerable GetEnumerable(TStore store); + public abstract void Add(ref TStore store, int? limit, T item); + } + } +} diff --git a/MoreLinq/MinBy.cs b/MoreLinq/MinBy.cs index 1a768fef0..67a0634da 100644 --- a/MoreLinq/MinBy.cs +++ b/MoreLinq/MinBy.cs @@ -19,6 +19,7 @@ namespace MoreLinq { using System; using System.Collections.Generic; + using System.Runtime.CompilerServices; static partial class MoreEnumerable { @@ -38,16 +39,17 @@ static partial class MoreEnumerable /// The sequence of minimal elements, according to the projection. /// or is null + [MethodImpl(MethodImplOptions.AggressiveInlining)] #if NET6_0_OR_GREATER + [Obsolete("MinBy() conflicts with new .NET Core method. Use MinElementsBy() instead.")] public static IExtremaEnumerable MinBy(IEnumerable source, Func selector) #else + [Obsolete("MinBy() conflicts with new .NET Core method. Use MinElementsBy() instead.")] public static IExtremaEnumerable MinBy(this IEnumerable source, Func selector) #endif - { - return MinBy(source, selector, null); - } + => MinElementsBy(source, selector); /// /// Returns the minimal elements of the given sequence, based on @@ -66,19 +68,16 @@ public static IExtremaEnumerable MinBy(this IEnumerable< /// , /// or is null + [MethodImpl(MethodImplOptions.AggressiveInlining)] #if NET6_0_OR_GREATER + [Obsolete("MinBy() conflicts with new .NET Core method. Use MinElementsBy() instead.")] public static IExtremaEnumerable MinBy(IEnumerable source, Func selector, IComparer? comparer) #else + [Obsolete("MinBy() conflicts with new .NET Core method. Use MinElementsBy() instead.")] public static IExtremaEnumerable MinBy(this IEnumerable source, Func selector, IComparer? comparer) #endif - { - if (source == null) throw new ArgumentNullException(nameof(source)); - if (selector == null) throw new ArgumentNullException(nameof(selector)); - - comparer ??= Comparer.Default; - return new ExtremaEnumerable(source, selector, (x, y) => -Math.Sign(comparer.Compare(x, y))); - } + => MinElementsBy(source, selector, comparer); } } diff --git a/MoreLinq/MinElementsBy.cs b/MoreLinq/MinElementsBy.cs new file mode 100644 index 000000000..80228251e --- /dev/null +++ b/MoreLinq/MinElementsBy.cs @@ -0,0 +1,74 @@ +#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 the minimal elements of the given sequence, based on + /// the given projection. + /// + /// + /// This overload uses the default comparer for the projected type. + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The sequence of minimal elements, according to the projection. + /// or is null + + public static IExtremaEnumerable MinElementsBy(this IEnumerable source, + Func selector) + { + return MinElementsBy(source, selector, null); + } + + /// + /// Returns the minimal elements of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// This operator uses deferred execution. The results are evaluated + /// and cached on first use to returned sequence. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// Comparer to use to compare projected values + /// The sequence of minimal elements, according to the projection. + /// , + /// or is null + + public static IExtremaEnumerable MinElementsBy(this IEnumerable source, + Func selector, IComparer? comparer) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (selector == null) throw new ArgumentNullException(nameof(selector)); + + comparer ??= Comparer.Default; + return new ExtremaEnumerable(source, selector, (x, y) => -Math.Sign(comparer.Compare(x, y))); + } + } +} diff --git a/MoreLinq/MoreLinq.csproj b/MoreLinq/MoreLinq.csproj index 71e664497..24f074d16 100644 --- a/MoreLinq/MoreLinq.csproj +++ b/MoreLinq/MoreLinq.csproj @@ -117,7 +117,7 @@ $([System.Text.RegularExpressions.Regex]::Replace($(Copyright), `\s+`, ` `).Trim()) MoreLINQ en-US - 3.3.2 + 4.0.0 MoreLINQ Developers. net451;net471;net472;netstandard1.0;netstandard1.6;netstandard2.0;netstandard2.1;netcoreapp2.0;net6.0 enable