diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..bdb0cabc8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/MoreLinq.sln b/MoreLinq.sln index 0924ab172..f9c1c67d6 100644 --- a/MoreLinq.sln +++ b/MoreLinq.sln @@ -1,95 +1,95 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{835F8FFA-471F-4322-B721-A897F27872FA}" - ProjectSection(SolutionItems) = preProject - build.cmd = build.cmd - buildw.cmd = buildw.cmd - COPYING.txt = COPYING.txt - pkg\morelinq.nuspec = pkg\morelinq.nuspec - pack.cmd = pack.cmd - packw.cmd = packw.cmd - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq", "MoreLinq\MoreLinq.csproj", "{8642E81B-3414-4C13-914F-05A4E600FE49}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Test", "MoreLinq.Test\MoreLinq.Test.csproj", "{D89B7AF5-7615-47B7-B894-A722E66DB3D8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuspecs", "Nuspecs", "{55D09D94-E557-4383-B5DB-9F15D43DAC72}" - ProjectSection(SolutionItems) = preProject - pkg\morelinq.nuspec = pkg\morelinq.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Acquire.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Acquire.nuspec - pkg\MoreLinq.Source.MoreEnumerable.AssertCount.nuspec = pkg\MoreLinq.Source.MoreEnumerable.AssertCount.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Batch.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Batch.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Concat.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Concat.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Consume.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Consume.nuspec - pkg\MoreLinq.Source.MoreEnumerable.DistinctBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.DistinctBy.nuspec - pkg\MoreLinq.Source.MoreEnumerable.EquiZip.nuspec = pkg\MoreLinq.Source.MoreEnumerable.EquiZip.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ExceptBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ExceptBy.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Fold.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Fold.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ForEach.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ForEach.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Generate.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Generate.nuspec - pkg\MoreLinq.Source.MoreEnumerable.GenerateByIndex.nuspec = pkg\MoreLinq.Source.MoreEnumerable.GenerateByIndex.nuspec - pkg\MoreLinq.Source.MoreEnumerable.GroupAdjacent.nuspec = pkg\MoreLinq.Source.MoreEnumerable.GroupAdjacent.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Index.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Index.nuspec - pkg\MoreLinq.Source.MoreEnumerable.MaxBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.MaxBy.nuspec - pkg\MoreLinq.Source.MoreEnumerable.MinBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.MinBy.nuspec - pkg\MoreLinq.Source.MoreEnumerable.nuspec = pkg\MoreLinq.Source.MoreEnumerable.nuspec - pkg\MoreLinq.Source.MoreEnumerable.OrderedMerge.nuspec = pkg\MoreLinq.Source.MoreEnumerable.OrderedMerge.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Pad.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pad.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Pairwise.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pairwise.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Pipe.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pipe.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Prepend.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Prepend.nuspec - pkg\MoreLinq.Source.MoreEnumerable.PreScan.nuspec = pkg\MoreLinq.Source.MoreEnumerable.PreScan.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Scan.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Scan.nuspec - pkg\MoreLinq.Source.MoreEnumerable.SingleOrFallback.nuspec = pkg\MoreLinq.Source.MoreEnumerable.SingleOrFallback.nuspec - pkg\MoreLinq.Source.MoreEnumerable.SkipUntil.nuspec = pkg\MoreLinq.Source.MoreEnumerable.SkipUntil.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Split.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Split.nuspec - pkg\MoreLinq.Source.MoreEnumerable.TakeEvery.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeEvery.nuspec - pkg\MoreLinq.Source.MoreEnumerable.TakeLast.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeLast.nuspec - pkg\MoreLinq.Source.MoreEnumerable.TakeUntil.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeUntil.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ToDataTable.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToDataTable.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ToDelimitedString.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToDelimitedString.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ToHashSet.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToHashSet.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Trace.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Trace.nuspec - pkg\MoreLinq.Source.MoreEnumerable.Zip.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Zip.nuspec - pkg\MoreLinq.Source.MoreEnumerable.ZipLongest.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ZipLongest.nuspec - pkg\MoreLinq.Portable.nuspec = pkg\MoreLinq.Portable.nuspec - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Portable", "MoreLinq\MoreLinq.Portable.csproj", "{72C49B06-715D-4423-AD0A-78517F71D7B9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Portable.Test", "MoreLinq.Test\MoreLinq.Portable.Test.csproj", "{3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8642E81B-3414-4C13-914F-05A4E600FE49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8642E81B-3414-4C13-914F-05A4E600FE49}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8642E81B-3414-4C13-914F-05A4E600FE49}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8642E81B-3414-4C13-914F-05A4E600FE49}.Release|Any CPU.Build.0 = Release|Any CPU - {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Release|Any CPU.Build.0 = Release|Any CPU - {72C49B06-715D-4423-AD0A-78517F71D7B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72C49B06-715D-4423-AD0A-78517F71D7B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72C49B06-715D-4423-AD0A-78517F71D7B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72C49B06-715D-4423-AD0A-78517F71D7B9}.Release|Any CPU.Build.0 = Release|Any CPU - {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - VisualSVNWorkingCopyRoot = - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{835F8FFA-471F-4322-B721-A897F27872FA}" + ProjectSection(SolutionItems) = preProject + build.cmd = build.cmd + buildw.cmd = buildw.cmd + COPYING.txt = COPYING.txt + pkg\morelinq.nuspec = pkg\morelinq.nuspec + pack.cmd = pack.cmd + packw.cmd = packw.cmd + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq", "MoreLinq\MoreLinq.csproj", "{8642E81B-3414-4C13-914F-05A4E600FE49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Test", "MoreLinq.Test\MoreLinq.Test.csproj", "{D89B7AF5-7615-47B7-B894-A722E66DB3D8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuspecs", "Nuspecs", "{55D09D94-E557-4383-B5DB-9F15D43DAC72}" + ProjectSection(SolutionItems) = preProject + pkg\morelinq.nuspec = pkg\morelinq.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Acquire.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Acquire.nuspec + pkg\MoreLinq.Source.MoreEnumerable.AssertCount.nuspec = pkg\MoreLinq.Source.MoreEnumerable.AssertCount.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Batch.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Batch.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Concat.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Concat.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Consume.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Consume.nuspec + pkg\MoreLinq.Source.MoreEnumerable.DistinctBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.DistinctBy.nuspec + pkg\MoreLinq.Source.MoreEnumerable.EquiZip.nuspec = pkg\MoreLinq.Source.MoreEnumerable.EquiZip.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ExceptBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ExceptBy.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Fold.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Fold.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ForEach.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ForEach.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Generate.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Generate.nuspec + pkg\MoreLinq.Source.MoreEnumerable.GenerateByIndex.nuspec = pkg\MoreLinq.Source.MoreEnumerable.GenerateByIndex.nuspec + pkg\MoreLinq.Source.MoreEnumerable.GroupAdjacent.nuspec = pkg\MoreLinq.Source.MoreEnumerable.GroupAdjacent.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Index.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Index.nuspec + pkg\MoreLinq.Source.MoreEnumerable.MaxBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.MaxBy.nuspec + pkg\MoreLinq.Source.MoreEnumerable.MinBy.nuspec = pkg\MoreLinq.Source.MoreEnumerable.MinBy.nuspec + pkg\MoreLinq.Source.MoreEnumerable.nuspec = pkg\MoreLinq.Source.MoreEnumerable.nuspec + pkg\MoreLinq.Source.MoreEnumerable.OrderedMerge.nuspec = pkg\MoreLinq.Source.MoreEnumerable.OrderedMerge.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Pad.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pad.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Pairwise.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pairwise.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Pipe.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Pipe.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Prepend.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Prepend.nuspec + pkg\MoreLinq.Source.MoreEnumerable.PreScan.nuspec = pkg\MoreLinq.Source.MoreEnumerable.PreScan.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Scan.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Scan.nuspec + pkg\MoreLinq.Source.MoreEnumerable.SingleOrFallback.nuspec = pkg\MoreLinq.Source.MoreEnumerable.SingleOrFallback.nuspec + pkg\MoreLinq.Source.MoreEnumerable.SkipUntil.nuspec = pkg\MoreLinq.Source.MoreEnumerable.SkipUntil.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Split.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Split.nuspec + pkg\MoreLinq.Source.MoreEnumerable.TakeEvery.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeEvery.nuspec + pkg\MoreLinq.Source.MoreEnumerable.TakeLast.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeLast.nuspec + pkg\MoreLinq.Source.MoreEnumerable.TakeUntil.nuspec = pkg\MoreLinq.Source.MoreEnumerable.TakeUntil.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ToDataTable.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToDataTable.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ToDelimitedString.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToDelimitedString.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ToHashSet.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ToHashSet.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Trace.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Trace.nuspec + pkg\MoreLinq.Source.MoreEnumerable.Zip.nuspec = pkg\MoreLinq.Source.MoreEnumerable.Zip.nuspec + pkg\MoreLinq.Source.MoreEnumerable.ZipLongest.nuspec = pkg\MoreLinq.Source.MoreEnumerable.ZipLongest.nuspec + pkg\MoreLinq.Portable.nuspec = pkg\MoreLinq.Portable.nuspec + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Portable", "MoreLinq\MoreLinq.Portable.csproj", "{72C49B06-715D-4423-AD0A-78517F71D7B9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoreLinq.Portable.Test", "MoreLinq.Test\MoreLinq.Portable.Test.csproj", "{3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8642E81B-3414-4C13-914F-05A4E600FE49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8642E81B-3414-4C13-914F-05A4E600FE49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8642E81B-3414-4C13-914F-05A4E600FE49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8642E81B-3414-4C13-914F-05A4E600FE49}.Release|Any CPU.Build.0 = Release|Any CPU + {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D89B7AF5-7615-47B7-B894-A722E66DB3D8}.Release|Any CPU.Build.0 = Release|Any CPU + {72C49B06-715D-4423-AD0A-78517F71D7B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72C49B06-715D-4423-AD0A-78517F71D7B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72C49B06-715D-4423-AD0A-78517F71D7B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72C49B06-715D-4423-AD0A-78517F71D7B9}.Release|Any CPU.Build.0 = Release|Any CPU + {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A47BCE6-B1A4-467A-BAF0-3021ED39FC7D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + VisualSVNWorkingCopyRoot = + EndGlobalSection +EndGlobal diff --git a/MoreLinq/Acquire.cs b/MoreLinq/Acquire.cs index 8d1eee4ce..09d8e2d45 100644 --- a/MoreLinq/Acquire.cs +++ b/MoreLinq/Acquire.cs @@ -1,60 +1,60 @@ -#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 - { - /// - /// Ensures that a source sequence of - /// objects are all acquired successfully. If the acquisition of any - /// one fails then those successfully - /// acquired till that point are disposed. - /// - /// Type of elements in sequence. - /// Source sequence of objects. - /// - /// Returns an array of all the acquired - /// object and in source order. - /// - /// - /// This operator executes immediately. - /// - - public static TSource[] Acquire(this IEnumerable source) - where TSource : IDisposable - { - if (source == null) throw new ArgumentNullException("source"); - - var disposables = new List(); - try - { - disposables.AddRange(source); - return disposables.ToArray(); - } - catch - { - foreach (var disposable in disposables) - disposable.Dispose(); - throw; - } - } - } +#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 + { + /// + /// Ensures that a source sequence of + /// objects are all acquired successfully. If the acquisition of any + /// one fails then those successfully + /// acquired till that point are disposed. + /// + /// Type of elements in sequence. + /// Source sequence of objects. + /// + /// Returns an array of all the acquired + /// object and in source order. + /// + /// + /// This operator executes immediately. + /// + + public static TSource[] Acquire(this IEnumerable source) + where TSource : IDisposable + { + if (source == null) throw new ArgumentNullException("source"); + + var disposables = new List(); + try + { + disposables.AddRange(source); + return disposables.ToArray(); + } + catch + { + foreach (var disposable in disposables) + disposable.Dispose(); + throw; + } + } + } } \ No newline at end of file diff --git a/MoreLinq/AssertCount.cs b/MoreLinq/AssertCount.cs index 1f97920b1..d9e5b4753 100644 --- a/MoreLinq/AssertCount.cs +++ b/MoreLinq/AssertCount.cs @@ -1,124 +1,124 @@ -#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 - { - #if MORELINQ - - private static readonly Func defaultErrorSelector = OnAssertCountFailure; - - /// - /// Asserts that a source sequence contains a given count of elements. - /// - /// Type of elements in sequence. - /// Source sequence. - /// Count to assert. - /// - /// Returns the original sequence as long it is contains the - /// number of elements specified by . - /// Otherwise it throws . - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable AssertCount(this IEnumerable source, - int count) - { - if (source == null) throw new ArgumentNullException("source"); - if (count < 0) throw new ArgumentOutOfRangeException("count"); - - return AssertCountImpl(source, count, defaultErrorSelector); - } - - /// - /// Asserts that a source sequence contains a given count of elements. - /// A parameter specifies the exception to be thrown. - /// - /// Type of elements in sequence. - /// Source sequence. - /// Count to assert. - /// Function that returns the object to throw. - /// - /// Returns the original sequence as long it is contains the - /// number of elements specified by . - /// Otherwise it throws the object - /// returned by calling . - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable AssertCount(this IEnumerable source, - int count, Func errorSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (count < 0) throw new ArgumentException(null, "count"); - if (errorSelector == null) throw new ArgumentNullException("errorSelector"); - - return AssertCountImpl(source, count, errorSelector); - } - - private static Exception OnAssertCountFailure(int cmp, int count) - { - var message = cmp < 0 - ? "Sequence contains too few elements when exactly {0} were expected." - : "Sequence contains too many elements when exactly {0} were expected."; - return new SequenceException(string.Format(message, count.ToString("N0"))); - } - - #endif - - private static IEnumerable AssertCountImpl(IEnumerable source, - int count, Func errorSelector) - { - var collection = source as ICollection; // Optimization for collections - if (collection != null) - { - if (collection.Count != count) - throw errorSelector(collection.Count.CompareTo(count), count); - return source; - } - - return ExpectingCountYieldingImpl(source, count, errorSelector); - } - - private static IEnumerable ExpectingCountYieldingImpl(IEnumerable source, - int count, Func errorSelector) - { - var iterations = 0; - foreach (var element in source) - { - iterations++; - if (iterations > count) - { - throw errorSelector(1, count); - } - yield return element; - } - if (iterations != count) - { - throw errorSelector(-1, count); - } - } - } +#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 + { + #if MORELINQ + + private static readonly Func defaultErrorSelector = OnAssertCountFailure; + + /// + /// Asserts that a source sequence contains a given count of elements. + /// + /// Type of elements in sequence. + /// Source sequence. + /// Count to assert. + /// + /// Returns the original sequence as long it is contains the + /// number of elements specified by . + /// Otherwise it throws . + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable AssertCount(this IEnumerable source, + int count) + { + if (source == null) throw new ArgumentNullException("source"); + if (count < 0) throw new ArgumentOutOfRangeException("count"); + + return AssertCountImpl(source, count, defaultErrorSelector); + } + + /// + /// Asserts that a source sequence contains a given count of elements. + /// A parameter specifies the exception to be thrown. + /// + /// Type of elements in sequence. + /// Source sequence. + /// Count to assert. + /// Function that returns the object to throw. + /// + /// Returns the original sequence as long it is contains the + /// number of elements specified by . + /// Otherwise it throws the object + /// returned by calling . + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable AssertCount(this IEnumerable source, + int count, Func errorSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (count < 0) throw new ArgumentException(null, "count"); + if (errorSelector == null) throw new ArgumentNullException("errorSelector"); + + return AssertCountImpl(source, count, errorSelector); + } + + private static Exception OnAssertCountFailure(int cmp, int count) + { + var message = cmp < 0 + ? "Sequence contains too few elements when exactly {0} were expected." + : "Sequence contains too many elements when exactly {0} were expected."; + return new SequenceException(string.Format(message, count.ToString("N0"))); + } + + #endif + + private static IEnumerable AssertCountImpl(IEnumerable source, + int count, Func errorSelector) + { + var collection = source as ICollection; // Optimization for collections + if (collection != null) + { + if (collection.Count != count) + throw errorSelector(collection.Count.CompareTo(count), count); + return source; + } + + return ExpectingCountYieldingImpl(source, count, errorSelector); + } + + private static IEnumerable ExpectingCountYieldingImpl(IEnumerable source, + int count, Func errorSelector) + { + var iterations = 0; + foreach (var element in source) + { + iterations++; + if (iterations > count) + { + throw errorSelector(1, count); + } + yield return element; + } + if (iterations != count) + { + throw errorSelector(-1, count); + } + } + } } \ No newline at end of file diff --git a/MoreLinq/Batch.cs b/MoreLinq/Batch.cs index 8c21f2683..bf3ee71c3 100644 --- a/MoreLinq/Batch.cs +++ b/MoreLinq/Batch.cs @@ -1,100 +1,100 @@ -#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; - using System.Diagnostics; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Batches the source sequence into sized buckets. - /// - /// Type of elements in sequence. - /// The source sequence. - /// Size of buckets. - /// A sequence of equally sized buckets containing elements of the source collection. - /// This operator uses deferred execution and streams its results (buckets and bucket content). - - public static IEnumerable> Batch(this IEnumerable source, int size) - { - return Batch(source, size, x => x); - } - - /// - /// Batches the source sequence into sized buckets and applies a projection to each bucket. - /// - /// Type of elements in sequence. - /// Type of result returned by . - /// The source sequence. - /// Size of buckets. - /// The projection to apply to each bucket. - /// A sequence of projections on equally sized buckets containing elements of the source collection. - /// This operator uses deferred execution and streams its results (buckets and bucket content). - - public static IEnumerable Batch(this IEnumerable source, int size, - Func, TResult> resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (size <= 0) throw new ArgumentOutOfRangeException("size"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - return BatchImpl(source, size, resultSelector); - } - - private static IEnumerable BatchImpl(this IEnumerable source, int size, - Func, TResult> resultSelector) - { - Debug.Assert(source != null); - Debug.Assert(size > 0); - Debug.Assert(resultSelector != null); - - TSource[] bucket = null; - var count = 0; - - foreach (var item in source) - { - if (bucket == null) - { - bucket = new TSource[size]; - } - - bucket[count++] = item; - - // The bucket is fully buffered before it's yielded - if (count != size) - { - continue; - } - - // Select is necessary so bucket contents are streamed too - yield return resultSelector(bucket.Select(x => x)); - - bucket = null; - count = 0; - } - - // Return the last bucket with all remaining elements - if (bucket != null && count > 0) - { - yield return resultSelector(bucket.Take(count)); - } - } - } -} +#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; + using System.Diagnostics; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Batches the source sequence into sized buckets. + /// + /// Type of elements in sequence. + /// The source sequence. + /// Size of buckets. + /// A sequence of equally sized buckets containing elements of the source collection. + /// This operator uses deferred execution and streams its results (buckets and bucket content). + + public static IEnumerable> Batch(this IEnumerable source, int size) + { + return Batch(source, size, x => x); + } + + /// + /// Batches the source sequence into sized buckets and applies a projection to each bucket. + /// + /// Type of elements in sequence. + /// Type of result returned by . + /// The source sequence. + /// Size of buckets. + /// The projection to apply to each bucket. + /// A sequence of projections on equally sized buckets containing elements of the source collection. + /// This operator uses deferred execution and streams its results (buckets and bucket content). + + public static IEnumerable Batch(this IEnumerable source, int size, + Func, TResult> resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (size <= 0) throw new ArgumentOutOfRangeException("size"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return BatchImpl(source, size, resultSelector); + } + + private static IEnumerable BatchImpl(this IEnumerable source, int size, + Func, TResult> resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(size > 0); + Debug.Assert(resultSelector != null); + + TSource[] bucket = null; + var count = 0; + + foreach (var item in source) + { + if (bucket == null) + { + bucket = new TSource[size]; + } + + bucket[count++] = item; + + // The bucket is fully buffered before it's yielded + if (count != size) + { + continue; + } + + // Select is necessary so bucket contents are streamed too + yield return resultSelector(bucket.Select(x => x)); + + bucket = null; + count = 0; + } + + // Return the last bucket with all remaining elements + if (bucket != null && count > 0) + { + yield return resultSelector(bucket.Take(count)); + } + } + } +} diff --git a/MoreLinq/Concat.cs b/MoreLinq/Concat.cs index e5ffc5423..37ebe355d 100644 --- a/MoreLinq/Concat.cs +++ b/MoreLinq/Concat.cs @@ -1,57 +1,57 @@ -#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 - -using LinqEnumerable = System.Linq.Enumerable; - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - - static partial class MoreEnumerable - { - /// - /// Returns a sequence consisting of the head element and the given tail elements. - /// - /// Type of sequence - /// Head element of the new sequence. - /// All elements of the tail. Must not be null. - /// A sequence consisting of the head elements and the given tail elements. - /// This operator uses deferred execution and streams its results. - - public static IEnumerable Concat(this T head, IEnumerable tail) - { - if (tail == null) throw new ArgumentNullException("tail"); - return tail.Prepend(head); - } - - /// - /// 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 Concat(this IEnumerable head, T tail) - { - if (head == null) throw new ArgumentNullException("head"); - return LinqEnumerable.Concat(head, LinqEnumerable.Repeat(tail, 1)); - } - } +#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 + +using LinqEnumerable = System.Linq.Enumerable; + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns a sequence consisting of the head element and the given tail elements. + /// + /// Type of sequence + /// Head element of the new sequence. + /// All elements of the tail. Must not be null. + /// A sequence consisting of the head elements and the given tail elements. + /// This operator uses deferred execution and streams its results. + + public static IEnumerable Concat(this T head, IEnumerable tail) + { + if (tail == null) throw new ArgumentNullException("tail"); + return tail.Prepend(head); + } + + /// + /// 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 Concat(this IEnumerable head, T tail) + { + if (head == null) throw new ArgumentNullException("head"); + return LinqEnumerable.Concat(head, LinqEnumerable.Repeat(tail, 1)); + } + } } \ No newline at end of file diff --git a/MoreLinq/Consume.cs b/MoreLinq/Consume.cs index 2690c5a45..dce393516 100644 --- a/MoreLinq/Consume.cs +++ b/MoreLinq/Consume.cs @@ -1,40 +1,40 @@ -#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 - { - /// - /// Completely consumes the given sequence. This method uses immediate execution, - /// and doesn't store any data during execution. - /// - /// Element type of the sequence - /// Source to consume - - public static void Consume(this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - foreach (var element in source) - { - } - } - } -} +#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 + { + /// + /// Completely consumes the given sequence. This method uses immediate execution, + /// and doesn't store any data during execution. + /// + /// Element type of the sequence + /// Source to consume + + public static void Consume(this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + foreach (var element in source) + { + } + } + } +} diff --git a/MoreLinq/DistinctBy.cs b/MoreLinq/DistinctBy.cs index 60710d32b..08609df33 100644 --- a/MoreLinq/DistinctBy.cs +++ b/MoreLinq/DistinctBy.cs @@ -1,103 +1,103 @@ -#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 NO_HASHSET -using System.Linq; -#endif - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - - static partial class MoreEnumerable - { - /// - /// Returns all distinct elements of the given source, where "distinctness" - /// is determined via a projection and the default equality comparer for the projected type. - /// - /// - /// This operator uses deferred execution and streams the results, although - /// a set of already-seen keys is retained. If a key is seen multiple times, - /// only the first element with that key is returned. - /// - /// Type of the source sequence - /// Type of the projected element - /// Source sequence - /// Projection for determining "distinctness" - /// A sequence consisting of distinct elements from the source sequence, - /// comparing them by the specified key projection. - - public static IEnumerable DistinctBy(this IEnumerable source, - Func keySelector) - { - return source.DistinctBy(keySelector, null); - } - - /// - /// Returns all distinct elements of the given source, where "distinctness" - /// is determined via a projection and the specified comparer for the projected type. - /// - /// - /// This operator uses deferred execution and streams the results, although - /// a set of already-seen keys is retained. If a key is seen multiple times, - /// only the first element with that key is returned. - /// - /// Type of the source sequence - /// Type of the projected element - /// Source sequence - /// Projection for determining "distinctness" - /// The equality comparer to use to determine whether or not keys are equal. - /// If null, the default equality comparer for TSource is used. - /// A sequence consisting of distinct elements from the source sequence, - /// comparing them by the specified key projection. - - public static IEnumerable DistinctBy(this IEnumerable source, - Func keySelector, IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - return DistinctByImpl(source, keySelector, comparer); - } - - private static IEnumerable DistinctByImpl(IEnumerable source, - Func keySelector, IEqualityComparer comparer) - { -#if !NO_HASHSET - var knownKeys = new HashSet(comparer); - foreach (var element in source) - { - if (knownKeys.Add(keySelector(element))) - { - yield return element; - } - } -#else - // - // On platforms where LINQ is available but no HashSet - // (like on Silverlight), implement this operator using - // existing LINQ operators. Using GroupBy is slightly less - // efficient since it has do all the grouping work before - // it can start to yield any one element from the source. - // - - return source.GroupBy(keySelector, comparer).Select(g => g.First()); -#endif - } - } -} +#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 NO_HASHSET +using System.Linq; +#endif + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns all distinct elements of the given source, where "distinctness" + /// is determined via a projection and the default equality comparer for the projected type. + /// + /// + /// This operator uses deferred execution and streams the results, although + /// a set of already-seen keys is retained. If a key is seen multiple times, + /// only the first element with that key is returned. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Projection for determining "distinctness" + /// A sequence consisting of distinct elements from the source sequence, + /// comparing them by the specified key projection. + + public static IEnumerable DistinctBy(this IEnumerable source, + Func keySelector) + { + return source.DistinctBy(keySelector, null); + } + + /// + /// Returns all distinct elements of the given source, where "distinctness" + /// is determined via a projection and the specified comparer for the projected type. + /// + /// + /// This operator uses deferred execution and streams the results, although + /// a set of already-seen keys is retained. If a key is seen multiple times, + /// only the first element with that key is returned. + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Projection for determining "distinctness" + /// The equality comparer to use to determine whether or not keys are equal. + /// If null, the default equality comparer for TSource is used. + /// A sequence consisting of distinct elements from the source sequence, + /// comparing them by the specified key projection. + + public static IEnumerable DistinctBy(this IEnumerable source, + Func keySelector, IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + return DistinctByImpl(source, keySelector, comparer); + } + + private static IEnumerable DistinctByImpl(IEnumerable source, + Func keySelector, IEqualityComparer comparer) + { +#if !NO_HASHSET + var knownKeys = new HashSet(comparer); + foreach (var element in source) + { + if (knownKeys.Add(keySelector(element))) + { + yield return element; + } + } +#else + // + // On platforms where LINQ is available but no HashSet + // (like on Silverlight), implement this operator using + // existing LINQ operators. Using GroupBy is slightly less + // efficient since it has do all the grouping work before + // it can start to yield any one element from the source. + // + + return source.GroupBy(keySelector, comparer).Select(g => g.First()); +#endif + } + } +} diff --git a/MoreLinq/EquiZip.cs b/MoreLinq/EquiZip.cs index 486892a33..38f068ab1 100644 --- a/MoreLinq/EquiZip.cs +++ b/MoreLinq/EquiZip.cs @@ -1,80 +1,80 @@ -#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 projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// - /// If the two input sequences are of different lengths then - /// is thrown. - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 1, 2, 3, 4 }; - /// string[] letters = { "A", "B", "C", "D" }; - /// var zipped = numbers.EquiZip(letters, (n, l) => n + l); - /// - /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", "4D" in turn. - /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in result sequence - /// First sequence - /// Second sequence - /// Function to apply to each pair of elements - - public static IEnumerable EquiZip(this IEnumerable first, - IEnumerable second, - Func resultSelector) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return EquiZipImpl(first, second, resultSelector); - } - - static IEnumerable EquiZipImpl( - IEnumerable first, - IEnumerable second, - Func resultSelector) - { - using (var e1 = first.GetEnumerator()) - using (var e2 = second.GetEnumerator()) - { - while (e1.MoveNext()) - { - if (e2.MoveNext()) - yield return resultSelector(e1.Current, e2.Current); - else - throw new InvalidOperationException("Second sequence ran out before first"); - } - if (e2.MoveNext()) - throw new InvalidOperationException("First sequence ran out before second"); - } - } - } -} +#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 projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the two input sequences are of different lengths then + /// is thrown. + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 1, 2, 3, 4 }; + /// string[] letters = { "A", "B", "C", "D" }; + /// var zipped = numbers.EquiZip(letters, (n, l) => n + l); + /// + /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", "4D" in turn. + /// + /// Type of elements in first sequence + /// Type of elements in second sequence + /// Type of elements in result sequence + /// First sequence + /// Second sequence + /// Function to apply to each pair of elements + + public static IEnumerable EquiZip(this IEnumerable first, + IEnumerable second, + Func resultSelector) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return EquiZipImpl(first, second, resultSelector); + } + + static IEnumerable EquiZipImpl( + IEnumerable first, + IEnumerable second, + Func resultSelector) + { + using (var e1 = first.GetEnumerator()) + using (var e2 = second.GetEnumerator()) + { + while (e1.MoveNext()) + { + if (e2.MoveNext()) + yield return resultSelector(e1.Current, e2.Current); + else + throw new InvalidOperationException("Second sequence ran out before first"); + } + if (e2.MoveNext()) + throw new InvalidOperationException("First sequence ran out before second"); + } + } + } +} diff --git a/MoreLinq/ExceptBy.cs b/MoreLinq/ExceptBy.cs index 76ba9fea8..0de05fbeb 100644 --- a/MoreLinq/ExceptBy.cs +++ b/MoreLinq/ExceptBy.cs @@ -1,102 +1,102 @@ -#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; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Returns the set of elements in the first sequence which aren't - /// in the second sequence, according to a given key selector. - /// - /// - /// This is a set operation; if multiple elements in have - /// equal keys, only the first such element is returned. - /// This operator uses deferred execution and streams the results, although - /// a set of keys from is immediately selected and retained. - /// - /// The type of the elements in the input sequences. - /// The type of the key returned by . - /// The sequence of potentially included elements. - /// The sequence of elements whose keys may prevent elements in - /// from being returned. - /// The mapping from source element to key. - /// A sequence of elements from whose key was not also a key for - /// any element in . - - public static IEnumerable ExceptBy(this IEnumerable first, - IEnumerable second, - Func keySelector) - { - return ExceptBy(first, second, keySelector, null); - } - - /// - /// Returns the set of elements in the first sequence which aren't - /// in the second sequence, according to a given key selector. - /// - /// - /// This is a set operation; if multiple elements in have - /// equal keys, only the first such element is returned. - /// This operator uses deferred execution and streams the results, although - /// a set of keys from is immediately selected and retained. - /// - /// The type of the elements in the input sequences. - /// The type of the key returned by . - /// The sequence of potentially included elements. - /// The sequence of elements whose keys may prevent elements in - /// from being returned. - /// The mapping from source element to key. - /// The equality comparer to use to determine whether or not keys are equal. - /// If null, the default equality comparer for TSource is used. - /// A sequence of elements from whose key was not also a key for - /// any element in . - - public static IEnumerable ExceptBy(this IEnumerable first, - IEnumerable second, - Func keySelector, - IEqualityComparer keyComparer) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - return ExceptByImpl(first, second, keySelector, keyComparer); - } - - private static IEnumerable ExceptByImpl(this IEnumerable first, - IEnumerable second, - Func keySelector, - IEqualityComparer keyComparer) - { - var keys = new HashSet(second.Select(keySelector), keyComparer); - foreach (var element in first) - { - var key = keySelector(element); - if (keys.Contains(key)) - { - continue; - } - yield return element; - keys.Add(key); - } - } - } -} +#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; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Returns the set of elements in the first sequence which aren't + /// in the second sequence, according to a given key selector. + /// + /// + /// This is a set operation; if multiple elements in have + /// equal keys, only the first such element is returned. + /// This operator uses deferred execution and streams the results, although + /// a set of keys from is immediately selected and retained. + /// + /// The type of the elements in the input sequences. + /// The type of the key returned by . + /// The sequence of potentially included elements. + /// The sequence of elements whose keys may prevent elements in + /// from being returned. + /// The mapping from source element to key. + /// A sequence of elements from whose key was not also a key for + /// any element in . + + public static IEnumerable ExceptBy(this IEnumerable first, + IEnumerable second, + Func keySelector) + { + return ExceptBy(first, second, keySelector, null); + } + + /// + /// Returns the set of elements in the first sequence which aren't + /// in the second sequence, according to a given key selector. + /// + /// + /// This is a set operation; if multiple elements in have + /// equal keys, only the first such element is returned. + /// This operator uses deferred execution and streams the results, although + /// a set of keys from is immediately selected and retained. + /// + /// The type of the elements in the input sequences. + /// The type of the key returned by . + /// The sequence of potentially included elements. + /// The sequence of elements whose keys may prevent elements in + /// from being returned. + /// The mapping from source element to key. + /// The equality comparer to use to determine whether or not keys are equal. + /// If null, the default equality comparer for TSource is used. + /// A sequence of elements from whose key was not also a key for + /// any element in . + + public static IEnumerable ExceptBy(this IEnumerable first, + IEnumerable second, + Func keySelector, + IEqualityComparer keyComparer) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + return ExceptByImpl(first, second, keySelector, keyComparer); + } + + private static IEnumerable ExceptByImpl(this IEnumerable first, + IEnumerable second, + Func keySelector, + IEqualityComparer keyComparer) + { + var keys = new HashSet(second.Select(keySelector), keyComparer); + foreach (var element in first) + { + var key = keySelector(element); + if (keys.Contains(key)) + { + continue; + } + yield return element; + keys.Add(key); + } + } + } +} diff --git a/MoreLinq/Fold.cs b/MoreLinq/Fold.cs index 77a96fdbc..50d512e70 100644 --- a/MoreLinq/Fold.cs +++ b/MoreLinq/Fold.cs @@ -1,64 +1,64 @@ -#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 - { - static TResult FoldImpl(IEnumerable source, int count, - Func folder1, - Func folder2, - Func folder3, - Func folder4) - { - if (source == null) throw new ArgumentNullException("source"); - if ( count == 1 && folder1 == null - || count == 2 && folder2 == null - || count == 3 && folder3 == null - || count == 4 && folder4 == null) - { // ReSharper disable NotResolvedInText - throw new ArgumentNullException("folder"); // ReSharper restore NotResolvedInText - } - - var elements = new T[count]; - foreach (var e in AssertCountImpl(source.Index(), count, OnFolderSourceSizeErrorSelector)) - elements[e.Key] = e.Value; - - switch (count) - { - 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]); - default: throw new NotSupportedException(); - } - } - - static readonly Func OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError; - - static Exception OnFolderSourceSizeError(int cmp, int count) - { - var message = cmp < 0 - ? "Sequence contains too few elements when exactly {0} {1} expected." - : "Sequence contains too many elements when exactly {0} {1} expected."; - return new Exception(string.Format(message, count.ToString("N0"), count == 1 ? "was" : "were")); - } - } -} +#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 + { + static TResult FoldImpl(IEnumerable source, int count, + Func folder1, + Func folder2, + Func folder3, + Func folder4) + { + if (source == null) throw new ArgumentNullException("source"); + if ( count == 1 && folder1 == null + || count == 2 && folder2 == null + || count == 3 && folder3 == null + || count == 4 && folder4 == null) + { // ReSharper disable NotResolvedInText + throw new ArgumentNullException("folder"); // ReSharper restore NotResolvedInText + } + + var elements = new T[count]; + foreach (var e in AssertCountImpl(source.Index(), count, OnFolderSourceSizeErrorSelector)) + elements[e.Key] = e.Value; + + switch (count) + { + 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]); + default: throw new NotSupportedException(); + } + } + + static readonly Func OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError; + + static Exception OnFolderSourceSizeError(int cmp, int count) + { + var message = cmp < 0 + ? "Sequence contains too few elements when exactly {0} {1} expected." + : "Sequence contains too many elements when exactly {0} {1} expected."; + return new Exception(string.Format(message, count.ToString("N0"), count == 1 ? "was" : "were")); + } + } +} diff --git a/MoreLinq/Fold.g.cs b/MoreLinq/Fold.g.cs index 7f3ce48b8..19b81cb5b 100644 --- a/MoreLinq/Fold.g.cs +++ b/MoreLinq/Fold.g.cs @@ -1,98 +1,98 @@ -#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; - - partial class MoreEnumerable - { - /// - /// Returns the result of applying a function to a sequence of - /// 1 element. - /// - /// - /// This operator uses immediate execution and effectively buffers - /// as many items of the source sequence as necessary. - /// - /// Type of element in the source sequence - /// Type of the result - /// The sequence of items to fold. - /// Function to apply to the elements in the sequence. - - public static TResult Fold(this IEnumerable source, Func folder) - { - return FoldImpl(source, 1, folder, null, null, null); - } - - /// - /// Returns the result of applying a function to a sequence of - /// 2 elements. - /// - /// - /// This operator uses immediate execution and effectively buffers - /// as many items of the source sequence as necessary. - /// - /// Type of element in the source sequence - /// Type of the result - /// The sequence of items to fold. - /// Function to apply to the elements in the sequence. - - public static TResult Fold(this IEnumerable source, Func folder) - { - return FoldImpl(source, 2, null, folder, null, null); - } - - /// - /// Returns the result of applying a function to a sequence of - /// 3 elements. - /// - /// - /// This operator uses immediate execution and effectively buffers - /// as many items of the source sequence as necessary. - /// - /// Type of element in the source sequence - /// Type of the result - /// The sequence of items to fold. - /// Function to apply to the elements in the sequence. - - public static TResult Fold(this IEnumerable source, Func folder) - { - return FoldImpl(source, 3, null, null, folder, null); - } - - /// - /// Returns the result of applying a function to a sequence of - /// 4 elements. - /// - /// - /// This operator uses immediate execution and effectively buffers - /// as many items of the source sequence as necessary. - /// - /// Type of element in the source sequence - /// Type of the result - /// The sequence of items to fold. - /// Function to apply to the elements in the sequence. - - public static TResult Fold(this IEnumerable source, Func folder) - { - return FoldImpl(source, 4, null, null, null, folder); - } - - } -} +#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; + + partial class MoreEnumerable + { + /// + /// Returns the result of applying a function to a sequence of + /// 1 element. + /// + /// + /// This operator uses immediate execution and effectively buffers + /// as many items of the source sequence as necessary. + /// + /// Type of element in the source sequence + /// Type of the result + /// The sequence of items to fold. + /// Function to apply to the elements in the sequence. + + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 1, folder, null, null, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 2 elements. + /// + /// + /// This operator uses immediate execution and effectively buffers + /// as many items of the source sequence as necessary. + /// + /// Type of element in the source sequence + /// Type of the result + /// The sequence of items to fold. + /// Function to apply to the elements in the sequence. + + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 2, null, folder, null, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 3 elements. + /// + /// + /// This operator uses immediate execution and effectively buffers + /// as many items of the source sequence as necessary. + /// + /// Type of element in the source sequence + /// Type of the result + /// The sequence of items to fold. + /// Function to apply to the elements in the sequence. + + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 3, null, null, folder, null); + } + + /// + /// Returns the result of applying a function to a sequence of + /// 4 elements. + /// + /// + /// This operator uses immediate execution and effectively buffers + /// as many items of the source sequence as necessary. + /// + /// Type of element in the source sequence + /// Type of the result + /// The sequence of items to fold. + /// Function to apply to the elements in the sequence. + + public static TResult Fold(this IEnumerable source, Func folder) + { + return FoldImpl(source, 4, null, null, null, folder); + } + + } +} diff --git a/MoreLinq/Fold.g.tt b/MoreLinq/Fold.g.tt index b17f26769..40dc2440d 100644 --- a/MoreLinq/Fold.g.tt +++ b/MoreLinq/Fold.g.tt @@ -1,67 +1,67 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Globalization" #> -<#@ import namespace="System.Linq" #> -#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; - - partial class MoreEnumerable - { -<# const int max = 4; - var overloads = - from i in Enumerable.Range(1, max) - let istr = i.ToString(CultureInfo.InvariantCulture) - select new - { - Ts = string.Join(", ", Enumerable.Repeat("T", i)), - Count = i, - CountElements = istr + " " + (i == 1 ? "element" : "elements"), - CountArg = istr, - FolderArgs = string.Join(", ", Enumerable.Repeat("null", i - 1) - .Concat(new[] { "folder" }) - .Concat(Enumerable.Repeat("null", max - i))), - - }; - - foreach (var e in overloads) { #> - /// - /// Returns the result of applying a function to a sequence of - /// <#= e.CountElements #>. - /// - /// - /// This operator uses immediate execution and effectively buffers - /// as many items of the source sequence as necessary. - /// - /// Type of element in the source sequence - /// Type of the result - /// The sequence of items to fold. - /// Function to apply to the elements in the sequence. - - public static TResult Fold(this IEnumerable source, Func<<#= e.Ts #>, TResult> folder) - { - return FoldImpl(source, <#= e.CountArg #>, <#= e.FolderArgs #>); - } - -<# } #> - } -} +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#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; + + partial class MoreEnumerable + { +<# const int max = 4; + var overloads = + from i in Enumerable.Range(1, max) + let istr = i.ToString(CultureInfo.InvariantCulture) + select new + { + Ts = string.Join(", ", Enumerable.Repeat("T", i)), + Count = i, + CountElements = istr + " " + (i == 1 ? "element" : "elements"), + CountArg = istr, + FolderArgs = string.Join(", ", Enumerable.Repeat("null", i - 1) + .Concat(new[] { "folder" }) + .Concat(Enumerable.Repeat("null", max - i))), + + }; + + foreach (var e in overloads) { #> + /// + /// Returns the result of applying a function to a sequence of + /// <#= e.CountElements #>. + /// + /// + /// This operator uses immediate execution and effectively buffers + /// as many items of the source sequence as necessary. + /// + /// Type of element in the source sequence + /// Type of the result + /// The sequence of items to fold. + /// Function to apply to the elements in the sequence. + + public static TResult Fold(this IEnumerable source, Func<<#= e.Ts #>, TResult> folder) + { + return FoldImpl(source, <#= e.CountArg #>, <#= e.FolderArgs #>); + } + +<# } #> + } +} diff --git a/MoreLinq/ForEach.cs b/MoreLinq/ForEach.cs index c0893a162..b45ce79d6 100644 --- a/MoreLinq/ForEach.cs +++ b/MoreLinq/ForEach.cs @@ -1,42 +1,42 @@ -#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 - { - /// - /// Immediately executes the given action on each element in the source sequence. - /// - /// The type of the elements in the sequence - /// The sequence of elements - /// The action to execute on each element - - public static void ForEach(this IEnumerable source, Action action) - { - if (source == null) throw new ArgumentNullException("source"); - if (action == null) throw new ArgumentNullException("action"); - foreach (var element in source) - { - action(element); - } - } - } -} +#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 + { + /// + /// Immediately executes the given action on each element in the source sequence. + /// + /// The type of the elements in the sequence + /// The sequence of elements + /// The action to execute on each element + + public static void ForEach(this IEnumerable source, Action action) + { + if (source == null) throw new ArgumentNullException("source"); + if (action == null) throw new ArgumentNullException("action"); + foreach (var element in source) + { + action(element); + } + } + } +} diff --git a/MoreLinq/Generate.cs b/MoreLinq/Generate.cs index ec0a67624..444fec6a7 100644 --- a/MoreLinq/Generate.cs +++ b/MoreLinq/Generate.cs @@ -1,59 +1,59 @@ -#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 of values consecutively generated by a generator function. - /// - /// Type of elements to generate. - /// Value of first element in sequence - /// - /// Generator function which takes the previous series element and uses it to generate the next element. - /// - /// - /// This function defers element generation until needed and streams the results. - /// - /// - /// - /// IEnumerable<int> result = Sequence.Generate(2, n => n * n).Take(5); - /// - /// The result variable, when iterated over, will yield 2, 4, 16, 256, and 65536, in turn. - /// - - public static IEnumerable Generate(TResult initial, Func generator) - { - if (generator == null) throw new ArgumentNullException("generator"); - return GenerateImpl(initial, generator); - } - - private static IEnumerable GenerateImpl(TResult initial, Func generator) - { - var current = initial; - while (true) - { - yield return current; - current = generator(current); - } - } - } -} +#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 of values consecutively generated by a generator function. + /// + /// Type of elements to generate. + /// Value of first element in sequence + /// + /// Generator function which takes the previous series element and uses it to generate the next element. + /// + /// + /// This function defers element generation until needed and streams the results. + /// + /// + /// + /// IEnumerable<int> result = Sequence.Generate(2, n => n * n).Take(5); + /// + /// The result variable, when iterated over, will yield 2, 4, 16, 256, and 65536, in turn. + /// + + public static IEnumerable Generate(TResult initial, Func generator) + { + if (generator == null) throw new ArgumentNullException("generator"); + return GenerateImpl(initial, generator); + } + + private static IEnumerable GenerateImpl(TResult initial, Func generator) + { + var current = initial; + while (true) + { + yield return current; + current = generator(current); + } + } + } +} diff --git a/MoreLinq/GenerateByIndex.cs b/MoreLinq/GenerateByIndex.cs index 13988d8fc..06abf14a0 100644 --- a/MoreLinq/GenerateByIndex.cs +++ b/MoreLinq/GenerateByIndex.cs @@ -1,56 +1,56 @@ -#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 of values based on indexes. - /// - /// - /// The sequence is (practically) infinite - /// - the index ranges from 0 to int.MaxValue inclusive. This function defers - /// execution and streams the results. - /// - /// Type of result to generate - /// Generation function to apply to each index - /// A sequence - - public static IEnumerable GenerateByIndex(Func generator) - { - // Would just use Enumerable.Range(0, int.MaxValue).Select(generator) but that doesn't - // include int.MaxValue. Picky, I know... - if (generator == null) throw new ArgumentNullException("generator"); - return GenerateByIndexImpl(generator); - } - - private static IEnumerable GenerateByIndexImpl(Func generator) - { - // Looping over 0...int.MaxValue inclusive is a pain. Simplest is to go exclusive, - // then go again for int.MaxValue. - for (var i = 0; i < int.MaxValue; i++) - { - yield return generator(i); - } - yield return generator(int.MaxValue); - } - } -} +#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 of values based on indexes. + /// + /// + /// The sequence is (practically) infinite + /// - the index ranges from 0 to int.MaxValue inclusive. This function defers + /// execution and streams the results. + /// + /// Type of result to generate + /// Generation function to apply to each index + /// A sequence + + public static IEnumerable GenerateByIndex(Func generator) + { + // Would just use Enumerable.Range(0, int.MaxValue).Select(generator) but that doesn't + // include int.MaxValue. Picky, I know... + if (generator == null) throw new ArgumentNullException("generator"); + return GenerateByIndexImpl(generator); + } + + private static IEnumerable GenerateByIndexImpl(Func generator) + { + // Looping over 0...int.MaxValue inclusive is a pain. Simplest is to go exclusive, + // then go again for int.MaxValue. + for (var i = 0; i < int.MaxValue; i++) + { + yield return generator(i); + } + yield return generator(int.MaxValue); + } + } +} diff --git a/MoreLinq/GroupAdjacent.cs b/MoreLinq/GroupAdjacent.cs index 3f42716e7..29f0d6307 100644 --- a/MoreLinq/GroupAdjacent.cs +++ b/MoreLinq/GroupAdjacent.cs @@ -1,252 +1,252 @@ -#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.Collections.ObjectModel; - using System.Diagnostics; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Groups the adjacent elements of a sequence according to a - /// specified key selector function. - /// - /// The type of the elements of - /// . - /// The type of the key returned by - /// . - /// A sequence whose elements to group. - /// A function to extract the key for each - /// element. - /// A sequence of groupings where each grouping - /// () contains the key - /// and the adjacent elements in the same order as found in the - /// source sequence. - /// - /// This method is implemented by using deferred execution and - /// streams the groupings. The grouping elements, however, are - /// buffered. Each grouping is therefore yielded as soon as it - /// is complete and before the next grouping occurs. - /// - - public static IEnumerable> GroupAdjacent( - this IEnumerable source, - Func keySelector) - { - return GroupAdjacent(source, keySelector, null); - } - - /// - /// Groups the adjacent elements of a sequence according to a - /// specified key selector function and compares the keys by using a - /// specified comparer. - /// - /// The type of the elements of - /// . - /// The type of the key returned by - /// . - /// A sequence whose elements to group. - /// A function to extract the key for each - /// element. - /// An to - /// compare keys. - /// A sequence of groupings where each grouping - /// () contains the key - /// and the adjacent elements in the same order as found in the - /// source sequence. - /// - /// This method is implemented by using deferred execution and - /// streams the groupings. The grouping elements, however, are - /// buffered. Each grouping is therefore yielded as soon as it - /// is complete and before the next grouping occurs. - /// - - public static IEnumerable> GroupAdjacent( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - - return GroupAdjacent(source, keySelector, e => e, comparer); - } - - /// - /// Groups the adjacent elements of a sequence according to a - /// specified key selector function and projects the elements for - /// each group by using a specified function. - /// - /// The type of the elements of - /// . - /// The type of the key returned by - /// . - /// The type of the elements in the - /// resulting groupings. - /// A sequence whose elements to group. - /// A function to extract the key for each - /// element. - /// A function to map each source - /// element to an element in the resulting grouping. - /// A sequence of groupings where each grouping - /// () contains the key - /// and the adjacent elements (of type ) - /// in the same order as found in the source sequence. - /// - /// This method is implemented by using deferred execution and - /// streams the groupings. The grouping elements, however, are - /// buffered. Each grouping is therefore yielded as soon as it - /// is complete and before the next grouping occurs. - /// - - public static IEnumerable> GroupAdjacent( - this IEnumerable source, - Func keySelector, - Func elementSelector) - { - return GroupAdjacent(source, keySelector, elementSelector, null); - } - - /// - /// Groups the adjacent elements of a sequence according to a - /// specified key selector function. The keys are compared by using - /// a comparer and each group's elements are projected by using a - /// specified function. - /// - /// The type of the elements of - /// . - /// The type of the key returned by - /// . - /// The type of the elements in the - /// resulting groupings. - /// A sequence whose elements to group. - /// A function to extract the key for each - /// element. - /// A function to map each source - /// element to an element in the resulting grouping. - /// An to - /// compare keys. - /// A sequence of groupings where each grouping - /// () contains the key - /// and the adjacent elements (of type ) - /// in the same order as found in the source sequence. - /// - /// This method is implemented by using deferred execution and - /// streams the groupings. The grouping elements, however, are - /// buffered. Each grouping is therefore yielded as soon as it - /// is complete and before the next grouping occurs. - /// - - public static IEnumerable> GroupAdjacent( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - - return GroupAdjacentImpl(source, keySelector, elementSelector, - comparer ?? EqualityComparer.Default); - } - - private static IEnumerable> GroupAdjacentImpl( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer) - { - Debug.Assert(source != null); - Debug.Assert(keySelector != null); - Debug.Assert(elementSelector != null); - Debug.Assert(comparer != null); - - using (var iterator = source.Select(item => new KeyValuePair(keySelector(item), elementSelector(item))) - .GetEnumerator()) - { - var group = default(TKey); - var members = (List) null; - - while (iterator.MoveNext()) - { - var item = iterator.Current; - if (members != null && comparer.Equals(group, item.Key)) - { - members.Add(item.Value); - } - else - { - if (members != null) - yield return CreateGroupAdjacentGrouping(group, members); - group = item.Key; - members = new List { item.Value }; - } - } - - if (members != null) - yield return CreateGroupAdjacentGrouping(group, members); - } - } - - private static Grouping CreateGroupAdjacentGrouping(TKey key, IList members) - { - Debug.Assert(members != null); - return Grouping.Create(key, members.IsReadOnly ? members : new ReadOnlyCollection(members)); - } - - static class Grouping - { - public static Grouping Create(TKey key, IEnumerable members) - { - return new Grouping(key, members); - } - } - - #if !NO_SERIALIZATION_ATTRIBUTES - [Serializable] - #endif - private sealed class Grouping : IGrouping - { - private readonly IEnumerable _members; - - public Grouping(TKey key, IEnumerable members) - { - Debug.Assert(members != null); - Key = key; - _members = members; - } - - public TKey Key { get; private set; } - - public IEnumerator GetEnumerator() - { - return _members.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } - } -} +#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.Collections.ObjectModel; + using System.Diagnostics; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Groups the adjacent elements of a sequence according to a + /// specified key selector function. + /// + /// The type of the elements of + /// . + /// The type of the key returned by + /// . + /// A sequence whose elements to group. + /// A function to extract the key for each + /// element. + /// A sequence of groupings where each grouping + /// () contains the key + /// and the adjacent elements in the same order as found in the + /// source sequence. + /// + /// This method is implemented by using deferred execution and + /// streams the groupings. The grouping elements, however, are + /// buffered. Each grouping is therefore yielded as soon as it + /// is complete and before the next grouping occurs. + /// + + public static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector) + { + return GroupAdjacent(source, keySelector, null); + } + + /// + /// Groups the adjacent elements of a sequence according to a + /// specified key selector function and compares the keys by using a + /// specified comparer. + /// + /// The type of the elements of + /// . + /// The type of the key returned by + /// . + /// A sequence whose elements to group. + /// A function to extract the key for each + /// element. + /// An to + /// compare keys. + /// A sequence of groupings where each grouping + /// () contains the key + /// and the adjacent elements in the same order as found in the + /// source sequence. + /// + /// This method is implemented by using deferred execution and + /// streams the groupings. The grouping elements, however, are + /// buffered. Each grouping is therefore yielded as soon as it + /// is complete and before the next grouping occurs. + /// + + public static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + + return GroupAdjacent(source, keySelector, e => e, comparer); + } + + /// + /// Groups the adjacent elements of a sequence according to a + /// specified key selector function and projects the elements for + /// each group by using a specified function. + /// + /// The type of the elements of + /// . + /// The type of the key returned by + /// . + /// The type of the elements in the + /// resulting groupings. + /// A sequence whose elements to group. + /// A function to extract the key for each + /// element. + /// A function to map each source + /// element to an element in the resulting grouping. + /// A sequence of groupings where each grouping + /// () contains the key + /// and the adjacent elements (of type ) + /// in the same order as found in the source sequence. + /// + /// This method is implemented by using deferred execution and + /// streams the groupings. The grouping elements, however, are + /// buffered. Each grouping is therefore yielded as soon as it + /// is complete and before the next grouping occurs. + /// + + public static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return GroupAdjacent(source, keySelector, elementSelector, null); + } + + /// + /// Groups the adjacent elements of a sequence according to a + /// specified key selector function. The keys are compared by using + /// a comparer and each group's elements are projected by using a + /// specified function. + /// + /// The type of the elements of + /// . + /// The type of the key returned by + /// . + /// The type of the elements in the + /// resulting groupings. + /// A sequence whose elements to group. + /// A function to extract the key for each + /// element. + /// A function to map each source + /// element to an element in the resulting grouping. + /// An to + /// compare keys. + /// A sequence of groupings where each grouping + /// () contains the key + /// and the adjacent elements (of type ) + /// in the same order as found in the source sequence. + /// + /// This method is implemented by using deferred execution and + /// streams the groupings. The grouping elements, however, are + /// buffered. Each grouping is therefore yielded as soon as it + /// is complete and before the next grouping occurs. + /// + + public static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + + return GroupAdjacentImpl(source, keySelector, elementSelector, + comparer ?? EqualityComparer.Default); + } + + private static IEnumerable> GroupAdjacentImpl( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + Debug.Assert(source != null); + Debug.Assert(keySelector != null); + Debug.Assert(elementSelector != null); + Debug.Assert(comparer != null); + + using (var iterator = source.Select(item => new KeyValuePair(keySelector(item), elementSelector(item))) + .GetEnumerator()) + { + var group = default(TKey); + var members = (List) null; + + while (iterator.MoveNext()) + { + var item = iterator.Current; + if (members != null && comparer.Equals(group, item.Key)) + { + members.Add(item.Value); + } + else + { + if (members != null) + yield return CreateGroupAdjacentGrouping(group, members); + group = item.Key; + members = new List { item.Value }; + } + } + + if (members != null) + yield return CreateGroupAdjacentGrouping(group, members); + } + } + + private static Grouping CreateGroupAdjacentGrouping(TKey key, IList members) + { + Debug.Assert(members != null); + return Grouping.Create(key, members.IsReadOnly ? members : new ReadOnlyCollection(members)); + } + + static class Grouping + { + public static Grouping Create(TKey key, IEnumerable members) + { + return new Grouping(key, members); + } + } + + #if !NO_SERIALIZATION_ATTRIBUTES + [Serializable] + #endif + private sealed class Grouping : IGrouping + { + private readonly IEnumerable _members; + + public Grouping(TKey key, IEnumerable members) + { + Debug.Assert(members != null); + Key = key; + _members = members; + } + + public TKey Key { get; private set; } + + public IEnumerator GetEnumerator() + { + return _members.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + } +} diff --git a/MoreLinq/Index.cs b/MoreLinq/Index.cs index 6ac66025c..fd7687007 100644 --- a/MoreLinq/Index.cs +++ b/MoreLinq/Index.cs @@ -1,58 +1,58 @@ -#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.Collections.Generic; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Returns a sequence of - /// where the key is the zero-based index of the value in the source - /// sequence. - /// - /// Type of elements in sequence. - /// The source sequence. - /// A sequence of . - /// This operator uses deferred execution and streams its - /// results. - - public static IEnumerable> Index(this IEnumerable source) - { - return source.Index(0); - } - - /// - /// Returns a sequence of - /// where the key is the index of the value in the source sequence. - /// An additional parameter specifies the starting index. - /// - /// Type of elements in sequence. - /// The source sequence. - /// - /// A sequence of . - /// This operator uses deferred execution and streams its - /// results. - - public static IEnumerable> Index(this IEnumerable source, int startIndex) - { - return source.Select((item, index) => new KeyValuePair(startIndex + index, item)); - } - } -} +#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.Collections.Generic; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Returns a sequence of + /// where the key is the zero-based index of the value in the source + /// sequence. + /// + /// Type of elements in sequence. + /// The source sequence. + /// A sequence of . + /// This operator uses deferred execution and streams its + /// results. + + public static IEnumerable> Index(this IEnumerable source) + { + return source.Index(0); + } + + /// + /// Returns a sequence of + /// where the key is the index of the value in the source sequence. + /// An additional parameter specifies the starting index. + /// + /// Type of elements in sequence. + /// The source sequence. + /// + /// A sequence of . + /// This operator uses deferred execution and streams its + /// results. + + public static IEnumerable> Index(this IEnumerable source, int startIndex) + { + return source.Select((item, index) => new KeyValuePair(startIndex + index, item)); + } + } +} diff --git a/MoreLinq/MaxBy.cs b/MoreLinq/MaxBy.cs index aa28dabe4..2080b21f6 100644 --- a/MoreLinq/MaxBy.cs +++ b/MoreLinq/MaxBy.cs @@ -1,97 +1,97 @@ -#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 maximal element of the given sequence, based on - /// the given projection. - /// - /// - /// If more than one element has the maximal projected value, the first - /// one encountered will be returned. This overload uses the default comparer - /// for the projected type. This operator uses immediate execution, but - /// only buffers a single result (the current maximal element). - /// - /// Type of the source sequence - /// Type of the projected element - /// Source sequence - /// Selector to use to pick the results to compare - /// The maximal element, according to the projection. - /// or is null - /// is empty - - public static TSource MaxBy(this IEnumerable source, - Func selector) - { - return source.MaxBy(selector, Comparer.Default); - } - - /// - /// Returns the maximal element of the given sequence, based on - /// the given projection and the specified comparer for projected values. - /// - /// - /// If more than one element has the maximal projected value, the first - /// one encountered will be returned. This overload uses the default comparer - /// for the projected type. This operator uses immediate execution, but - /// only buffers a single result (the current maximal element). - /// - /// 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 maximal element, according to the projection. - /// , - /// or is null - /// is empty - - public static TSource MaxBy(this IEnumerable source, - Func selector, IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (selector == null) throw new ArgumentNullException("selector"); - if (comparer == null) throw new ArgumentNullException("comparer"); - using (var sourceIterator = source.GetEnumerator()) - { - if (!sourceIterator.MoveNext()) - { - throw new InvalidOperationException("Sequence contains no elements"); - } - var max = sourceIterator.Current; - var maxKey = selector(max); - while (sourceIterator.MoveNext()) - { - var candidate = sourceIterator.Current; - var candidateProjected = selector(candidate); - if (comparer.Compare(candidateProjected, maxKey) > 0) - { - max = candidate; - maxKey = candidateProjected; - } - } - return max; - } - } - } -} +#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 maximal element of the given sequence, based on + /// the given projection. + /// + /// + /// If more than one element has the maximal projected value, the first + /// one encountered will be returned. This overload uses the default comparer + /// for the projected type. This operator uses immediate execution, but + /// only buffers a single result (the current maximal element). + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The maximal element, according to the projection. + /// or is null + /// is empty + + public static TSource MaxBy(this IEnumerable source, + Func selector) + { + return source.MaxBy(selector, Comparer.Default); + } + + /// + /// Returns the maximal element of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// If more than one element has the maximal projected value, the first + /// one encountered will be returned. This overload uses the default comparer + /// for the projected type. This operator uses immediate execution, but + /// only buffers a single result (the current maximal element). + /// + /// 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 maximal element, according to the projection. + /// , + /// or is null + /// is empty + + public static TSource MaxBy(this IEnumerable source, + Func selector, IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (selector == null) throw new ArgumentNullException("selector"); + if (comparer == null) throw new ArgumentNullException("comparer"); + using (var sourceIterator = source.GetEnumerator()) + { + if (!sourceIterator.MoveNext()) + { + throw new InvalidOperationException("Sequence contains no elements"); + } + var max = sourceIterator.Current; + var maxKey = selector(max); + while (sourceIterator.MoveNext()) + { + var candidate = sourceIterator.Current; + var candidateProjected = selector(candidate); + if (comparer.Compare(candidateProjected, maxKey) > 0) + { + max = candidate; + maxKey = candidateProjected; + } + } + return max; + } + } + } +} diff --git a/MoreLinq/MinBy.cs b/MoreLinq/MinBy.cs index 057a4c37a..cc96a9936 100644 --- a/MoreLinq/MinBy.cs +++ b/MoreLinq/MinBy.cs @@ -1,97 +1,97 @@ -#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 element of the given sequence, based on - /// the given projection. - /// - /// - /// If more than one element has the minimal projected value, the first - /// one encountered will be returned. This overload uses the default comparer - /// for the projected type. This operator uses immediate execution, but - /// only buffers a single result (the current minimal element). - /// - /// Type of the source sequence - /// Type of the projected element - /// Source sequence - /// Selector to use to pick the results to compare - /// The minimal element, according to the projection. - /// or is null - /// is empty - - public static TSource MinBy(this IEnumerable source, - Func selector) - { - return source.MinBy(selector, Comparer.Default); - } - - /// - /// Returns the minimal element of the given sequence, based on - /// the given projection and the specified comparer for projected values. - /// - /// - /// If more than one element has the minimal projected value, the first - /// one encountered will be returned. This overload uses the default comparer - /// for the projected type. This operator uses immediate execution, but - /// only buffers a single result (the current minimal element). - /// - /// 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 minimal element, according to the projection. - /// , - /// or is null - /// is empty - - public static TSource MinBy(this IEnumerable source, - Func selector, IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (selector == null) throw new ArgumentNullException("selector"); - if (comparer == null) throw new ArgumentNullException("comparer"); - using (var sourceIterator = source.GetEnumerator()) - { - if (!sourceIterator.MoveNext()) - { - throw new InvalidOperationException("Sequence contains no elements"); - } - var min = sourceIterator.Current; - var minKey = selector(min); - while (sourceIterator.MoveNext()) - { - var candidate = sourceIterator.Current; - var candidateProjected = selector(candidate); - if (comparer.Compare(candidateProjected, minKey) < 0) - { - min = candidate; - minKey = candidateProjected; - } - } - return min; - } - } - } -} +#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 element of the given sequence, based on + /// the given projection. + /// + /// + /// If more than one element has the minimal projected value, the first + /// one encountered will be returned. This overload uses the default comparer + /// for the projected type. This operator uses immediate execution, but + /// only buffers a single result (the current minimal element). + /// + /// Type of the source sequence + /// Type of the projected element + /// Source sequence + /// Selector to use to pick the results to compare + /// The minimal element, according to the projection. + /// or is null + /// is empty + + public static TSource MinBy(this IEnumerable source, + Func selector) + { + return source.MinBy(selector, Comparer.Default); + } + + /// + /// Returns the minimal element of the given sequence, based on + /// the given projection and the specified comparer for projected values. + /// + /// + /// If more than one element has the minimal projected value, the first + /// one encountered will be returned. This overload uses the default comparer + /// for the projected type. This operator uses immediate execution, but + /// only buffers a single result (the current minimal element). + /// + /// 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 minimal element, according to the projection. + /// , + /// or is null + /// is empty + + public static TSource MinBy(this IEnumerable source, + Func selector, IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (selector == null) throw new ArgumentNullException("selector"); + if (comparer == null) throw new ArgumentNullException("comparer"); + using (var sourceIterator = source.GetEnumerator()) + { + if (!sourceIterator.MoveNext()) + { + throw new InvalidOperationException("Sequence contains no elements"); + } + var min = sourceIterator.Current; + var minKey = selector(min); + while (sourceIterator.MoveNext()) + { + var candidate = sourceIterator.Current; + var candidateProjected = selector(candidate); + if (comparer.Compare(candidateProjected, minKey) < 0) + { + min = candidate; + minKey = candidateProjected; + } + } + return min; + } + } + } +} diff --git a/MoreLinq/MoreEnumerable.cs b/MoreLinq/MoreEnumerable.cs index f697ac8ee..6d3c6398a 100644 --- a/MoreLinq/MoreEnumerable.cs +++ b/MoreLinq/MoreEnumerable.cs @@ -1,31 +1,31 @@ -#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.Collections.Generic; - - /// - /// Provides a set of static methods for querying objects that - /// implement . The actual methods - /// are implemented in files reflecting the method name. - /// - - public static partial class MoreEnumerable - { - } -} +#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.Collections.Generic; + + /// + /// Provides a set of static methods for querying objects that + /// implement . The actual methods + /// are implemented in files reflecting the method name. + /// + + public static partial class MoreEnumerable + { + } +} diff --git a/MoreLinq/MoreLinq.Portable.csproj b/MoreLinq/MoreLinq.Portable.csproj index 6c42c8ac3..6e99fbc16 100644 --- a/MoreLinq/MoreLinq.Portable.csproj +++ b/MoreLinq/MoreLinq.Portable.csproj @@ -1,186 +1,186 @@ - - - - - 10.0 - Debug - AnyCPU - {72C49B06-715D-4423-AD0A-78517F71D7B9} - Library - Properties - MoreLinq - MoreLinq.Portable - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile328 - v4.0 - - - true - full - false - bin\Debug\ - TRACE;DEBUG;MORELINQ;NO_SERIALIZATION_ATTRIBUTES;NO_EXCEPTION_SERIALIZATION;NO_TRACING;NO_COM - prompt - 4 - bin\Debug\MoreLinq.Portable.XML - - - pdbonly - true - bin\Release\ - TRACE;MORELINQ;NO_SERIALIZATION_ATTRIBUTES;NO_EXCEPTION_SERIALIZATION;NO_TRACING;NO_COM - prompt - 4 - bin\Release\MoreLinq.Portable.XML - - - true - - - key.snk - - - - - TextTemplatingFileGenerator - Fold.g.cs - MoreEnumerable.cs - - - - TextTemplatingFileGenerator - ToDelimitedString.g.cs - MoreEnumerable.cs - - - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - True - True - Fold.g.tt - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - - MoreEnumerable.cs - - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - True - True - ToDelimitedString.g.tt - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - - - - - + + + + + 10.0 + Debug + AnyCPU + {72C49B06-715D-4423-AD0A-78517F71D7B9} + Library + Properties + MoreLinq + MoreLinq.Portable + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile328 + v4.0 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;MORELINQ;NO_SERIALIZATION_ATTRIBUTES;NO_EXCEPTION_SERIALIZATION;NO_TRACING;NO_COM + prompt + 4 + bin\Debug\MoreLinq.Portable.XML + + + pdbonly + true + bin\Release\ + TRACE;MORELINQ;NO_SERIALIZATION_ATTRIBUTES;NO_EXCEPTION_SERIALIZATION;NO_TRACING;NO_COM + prompt + 4 + bin\Release\MoreLinq.Portable.XML + + + true + + + key.snk + + + + + TextTemplatingFileGenerator + Fold.g.cs + MoreEnumerable.cs + + + + TextTemplatingFileGenerator + ToDelimitedString.g.cs + MoreEnumerable.cs + + + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + True + True + Fold.g.tt + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + + MoreEnumerable.cs + + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + True + True + ToDelimitedString.g.tt + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + + + + + \ No newline at end of file diff --git a/MoreLinq/MoreLinq.csproj b/MoreLinq/MoreLinq.csproj index 2603d99c9..86841cb0a 100644 --- a/MoreLinq/MoreLinq.csproj +++ b/MoreLinq/MoreLinq.csproj @@ -1,198 +1,198 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {8642E81B-3414-4C13-914F-05A4E600FE49} - Library - Properties - MoreLinq - MoreLinq - v3.5 - 512 - true - key.snk - - - 3.5 - - - - true - full - false - bin\Debug\ - TRACE;DEBUG;MORELINQ - prompt - 4 - bin\Debug\MoreLinq.xml - true - - - pdbonly - true - bin\Release\ - TRACE;MORELINQ - prompt - 4 - true - bin\Release\MoreLinq.xml - - - - - 3.5 - - - - - - - True - True - Fold.g.tt - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - True - True - ToDelimitedString.g.tt - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - MoreEnumerable.cs - - - TextTemplatingFileGenerator - ToDelimitedString.g.cs - MoreEnumerable.cs - - - MoreEnumerable.cs - - - TextTemplatingFileGenerator - Fold.g.cs - MoreEnumerable.cs - - - - - - - - - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {8642E81B-3414-4C13-914F-05A4E600FE49} + Library + Properties + MoreLinq + MoreLinq + v3.5 + 512 + true + key.snk + + + 3.5 + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;MORELINQ + prompt + 4 + bin\Debug\MoreLinq.xml + true + + + pdbonly + true + bin\Release\ + TRACE;MORELINQ + prompt + 4 + true + bin\Release\MoreLinq.xml + + + + + 3.5 + + + + + + + True + True + Fold.g.tt + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + True + True + ToDelimitedString.g.tt + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + MoreEnumerable.cs + + + TextTemplatingFileGenerator + ToDelimitedString.g.cs + MoreEnumerable.cs + + + MoreEnumerable.cs + + + TextTemplatingFileGenerator + Fold.g.cs + MoreEnumerable.cs + + + + + + + + + + + \ No newline at end of file diff --git a/MoreLinq/OrderedMerge.cs b/MoreLinq/OrderedMerge.cs index f885fd433..ded6b1ee3 100644 --- a/MoreLinq/OrderedMerge.cs +++ b/MoreLinq/OrderedMerge.cs @@ -1,265 +1,265 @@ -#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 -{ - #region Imports - - using System; - using System.Collections.Generic; - using System.Diagnostics; - - #endregion - - static partial class MoreEnumerable - { - /// - /// Merges two ordered sequences into one. Where the elements equal - /// in both sequences, the element from the first sequence is - /// returned in the resulting sequence. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second) - { - return OrderedMerge(first, second, null); - } - - /// - /// Merges two ordered sequences into one with an additional - /// parameter specifying how to compare the elements of the - /// sequences. Where the elements equal in both sequences, the - /// element from the first sequence is returned in the resulting - /// sequence. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - IComparer comparer) - { - return OrderedMerge(first, second, e => e, f => f, s => s, (a, _) => a, comparer); - } - - /// - /// Merges two ordered sequences into one with an additional - /// parameter specifying the element key by which the sequences are - /// ordered. Where the keys equal in both sequences, the - /// element from the first sequence is returned in the resulting - /// sequence. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered (by key) as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - Func keySelector) - { - return OrderedMerge(first, second, keySelector, a => a, b => b, (a, _) => a, null); - } - - /// - /// Merges two ordered sequences into one. Additional parameters - /// specify the element key by which the sequences are ordered, - /// the result when element is found in first sequence but not in - /// the second, the result when element is found in second sequence - /// but not in the first and the result when elements are found in - /// both sequences. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered (by key) as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - Func keySelector, - Func firstSelector, - Func secondSelector, - Func bothSelector) - { - return OrderedMerge(first, second, keySelector, firstSelector, secondSelector, bothSelector, null); - } - - /// - /// Merges two ordered sequences into one. Additional parameters - /// specify the element key by which the sequences are ordered, - /// the result when element is found in first sequence but not in - /// the second, the result when element is found in second sequence - /// but not in the first, the result when elements are found in - /// both sequences and a method for comparing keys. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered (by key) as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - Func keySelector, - Func firstSelector, - Func secondSelector, - Func bothSelector, - IComparer comparer) - { - return OrderedMerge(first, second, keySelector, keySelector, firstSelector, secondSelector, bothSelector, comparer); - } - - /// - /// Merges two heterogeneous sequences ordered by a common key type - /// into a homogeneous one. Additional parameters specify the - /// element key by which the sequences are ordered, the result when - /// element is found in first sequence but not in the second and - /// the result when element is found in second sequence but not in - /// the first, the result when elements are found in both sequences. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered (by key) as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - Func firstKeySelector, - Func secondKeySelector, - Func firstSelector, - Func secondSelector, - Func bothSelector) - { - return OrderedMerge(first, second, firstKeySelector, secondKeySelector, firstSelector, secondSelector, bothSelector, null); - } - - /// - /// Merges two heterogeneous sequences ordered by a common key type - /// into a homogeneous one. Additional parameters specify the - /// element key by which the sequences are ordered, the result when - /// element is found in first sequence but not in the second, - /// the result when element is found in second sequence but not in - /// the first, the result when elements are found in both sequences - /// and a method for comparing keys. - /// - /// - /// This method uses deferred execution. The behavior is undefined - /// if the sequences are unordered (by key) as inputs. - /// - - public static IEnumerable OrderedMerge( - this IEnumerable first, - IEnumerable second, - Func firstKeySelector, - Func secondKeySelector, - Func firstSelector, - Func secondSelector, - Func bothSelector, - IComparer comparer) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - if (firstKeySelector == null) throw new ArgumentNullException("firstKeySelector"); - if (secondKeySelector == null) throw new ArgumentNullException("secondKeySelector"); - if (firstSelector == null) throw new ArgumentNullException("firstSelector"); - if (bothSelector == null) throw new ArgumentNullException("bothSelector"); - if (secondSelector == null) throw new ArgumentNullException("secondSelector"); - - return OrderedMergeImpl(first, second, - firstKeySelector, secondKeySelector, - firstSelector, secondSelector, bothSelector, - comparer ?? Comparer.Default); - } - - static IEnumerable OrderedMergeImpl( - IEnumerable first, - IEnumerable second, - Func firstKeySelector, - Func secondKeySelector, - Func firstSelector, - Func secondSelector, - Func bothSelector, - IComparer comparer) - { - Debug.Assert(first != null); - Debug.Assert(second != null); - Debug.Assert(firstKeySelector != null); - Debug.Assert(secondKeySelector != null); - Debug.Assert(firstSelector != null); - Debug.Assert(secondSelector != null); - Debug.Assert(bothSelector != null); - Debug.Assert(comparer != null); - - using (var e1 = first.GetEnumerator()) - using (var e2 = second.GetEnumerator()) - { - var gotFirst = e1.MoveNext(); - var gotSecond = e2.MoveNext(); - - while (gotFirst || gotSecond) - { - if (gotFirst && gotSecond) - { - var element1 = e1.Current; - 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 - { - yield return bothSelector(element1, element2); - gotFirst = e1.MoveNext(); - gotSecond = e2.MoveNext(); - } - } - else if (gotSecond) - { - yield return secondSelector(e2.Current); - gotSecond = e2.MoveNext(); - } - else // (gotFirst) - { - yield return firstSelector(e1.Current); - gotFirst = e1.MoveNext(); - } - } - } - } - } +#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 +{ + #region Imports + + using System; + using System.Collections.Generic; + using System.Diagnostics; + + #endregion + + static partial class MoreEnumerable + { + /// + /// Merges two ordered sequences into one. Where the elements equal + /// in both sequences, the element from the first sequence is + /// returned in the resulting sequence. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second) + { + return OrderedMerge(first, second, null); + } + + /// + /// Merges two ordered sequences into one with an additional + /// parameter specifying how to compare the elements of the + /// sequences. Where the elements equal in both sequences, the + /// element from the first sequence is returned in the resulting + /// sequence. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + IComparer comparer) + { + return OrderedMerge(first, second, e => e, f => f, s => s, (a, _) => a, comparer); + } + + /// + /// Merges two ordered sequences into one with an additional + /// parameter specifying the element key by which the sequences are + /// ordered. Where the keys equal in both sequences, the + /// element from the first sequence is returned in the resulting + /// sequence. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered (by key) as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + Func keySelector) + { + return OrderedMerge(first, second, keySelector, a => a, b => b, (a, _) => a, null); + } + + /// + /// Merges two ordered sequences into one. Additional parameters + /// specify the element key by which the sequences are ordered, + /// the result when element is found in first sequence but not in + /// the second, the result when element is found in second sequence + /// but not in the first and the result when elements are found in + /// both sequences. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered (by key) as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + Func keySelector, + Func firstSelector, + Func secondSelector, + Func bothSelector) + { + return OrderedMerge(first, second, keySelector, firstSelector, secondSelector, bothSelector, null); + } + + /// + /// Merges two ordered sequences into one. Additional parameters + /// specify the element key by which the sequences are ordered, + /// the result when element is found in first sequence but not in + /// the second, the result when element is found in second sequence + /// but not in the first, the result when elements are found in + /// both sequences and a method for comparing keys. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered (by key) as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + Func keySelector, + Func firstSelector, + Func secondSelector, + Func bothSelector, + IComparer comparer) + { + return OrderedMerge(first, second, keySelector, keySelector, firstSelector, secondSelector, bothSelector, comparer); + } + + /// + /// Merges two heterogeneous sequences ordered by a common key type + /// into a homogeneous one. Additional parameters specify the + /// element key by which the sequences are ordered, the result when + /// element is found in first sequence but not in the second and + /// the result when element is found in second sequence but not in + /// the first, the result when elements are found in both sequences. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered (by key) as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + Func firstKeySelector, + Func secondKeySelector, + Func firstSelector, + Func secondSelector, + Func bothSelector) + { + return OrderedMerge(first, second, firstKeySelector, secondKeySelector, firstSelector, secondSelector, bothSelector, null); + } + + /// + /// Merges two heterogeneous sequences ordered by a common key type + /// into a homogeneous one. Additional parameters specify the + /// element key by which the sequences are ordered, the result when + /// element is found in first sequence but not in the second, + /// the result when element is found in second sequence but not in + /// the first, the result when elements are found in both sequences + /// and a method for comparing keys. + /// + /// + /// This method uses deferred execution. The behavior is undefined + /// if the sequences are unordered (by key) as inputs. + /// + + public static IEnumerable OrderedMerge( + this IEnumerable first, + IEnumerable second, + Func firstKeySelector, + Func secondKeySelector, + Func firstSelector, + Func secondSelector, + Func bothSelector, + IComparer comparer) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (firstKeySelector == null) throw new ArgumentNullException("firstKeySelector"); + if (secondKeySelector == null) throw new ArgumentNullException("secondKeySelector"); + if (firstSelector == null) throw new ArgumentNullException("firstSelector"); + if (bothSelector == null) throw new ArgumentNullException("bothSelector"); + if (secondSelector == null) throw new ArgumentNullException("secondSelector"); + + return OrderedMergeImpl(first, second, + firstKeySelector, secondKeySelector, + firstSelector, secondSelector, bothSelector, + comparer ?? Comparer.Default); + } + + static IEnumerable OrderedMergeImpl( + IEnumerable first, + IEnumerable second, + Func firstKeySelector, + Func secondKeySelector, + Func firstSelector, + Func secondSelector, + Func bothSelector, + IComparer comparer) + { + Debug.Assert(first != null); + Debug.Assert(second != null); + Debug.Assert(firstKeySelector != null); + Debug.Assert(secondKeySelector != null); + Debug.Assert(firstSelector != null); + Debug.Assert(secondSelector != null); + Debug.Assert(bothSelector != null); + Debug.Assert(comparer != null); + + using (var e1 = first.GetEnumerator()) + using (var e2 = second.GetEnumerator()) + { + var gotFirst = e1.MoveNext(); + var gotSecond = e2.MoveNext(); + + while (gotFirst || gotSecond) + { + if (gotFirst && gotSecond) + { + var element1 = e1.Current; + 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 + { + yield return bothSelector(element1, element2); + gotFirst = e1.MoveNext(); + gotSecond = e2.MoveNext(); + } + } + else if (gotSecond) + { + yield return secondSelector(e2.Current); + gotSecond = e2.MoveNext(); + } + else // (gotFirst) + { + yield return firstSelector(e1.Current); + gotFirst = e1.MoveNext(); + } + } + } + } + } } \ No newline at end of file diff --git a/MoreLinq/Pad.cs b/MoreLinq/Pad.cs index dd8809812..addd4bf84 100644 --- a/MoreLinq/Pad.cs +++ b/MoreLinq/Pad.cs @@ -1,136 +1,136 @@ -#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; - using System.Diagnostics; - - static partial class MoreEnumerable - { - /// - /// Pads a sequence with default values if it is narrower (shorter - /// in length) than a given width. - /// - /// The type of the elements of . - /// The sequence to pad. - /// The width/length below which to pad. - /// - /// Returns a sequence that is at least as wide/long as the width/length - /// specified by the parameter. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 123, 456, 789 }; - /// IEnumerable<int> result = numbers.Pad(5); - /// - /// The result variable, when iterated over, will yield - /// 123, 456, 789 and two zeroes, in turn. - /// - - public static IEnumerable Pad(this IEnumerable source, int width) - { - return Pad(source, width, default(TSource)); - } - - /// - /// Pads a sequence with a given filler value if it is narrower (shorter - /// in length) than a given width. - /// - /// The type of the elements of . - /// The sequence to pad. - /// The width/length below which to pad. - /// The value to use for padding. - /// - /// Returns a sequence that is at least as wide/long as the width/length - /// specified by the parameter. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 123, 456, 789 }; - /// IEnumerable<int> result = numbers.Pad(5, -1); - /// - /// The result variable, when iterated over, will yield - /// 123, 456, and 789 followed by two occurrences of -1, in turn. - /// - - public static IEnumerable Pad(this IEnumerable source, int width, TSource padding) - { - if (source == null) throw new ArgumentNullException("source"); - if (width < 0) throw new ArgumentException(null, "width"); - return PadImpl(source, width, padding, null); - } - - /// - /// Pads a sequence with a dynamic filler value if it is narrower (shorter - /// in length) than a given width. - /// - /// The type of the elements of . - /// The sequence to pad. - /// The width/length below which to pad. - /// Function to calculate padding. - /// - /// Returns a sequence that is at least as wide/long as the width/length - /// specified by the parameter. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 0, 1, 2 }; - /// IEnumerable<int> result = numbers.Pad(5, i => -i); - /// - /// The result variable, when iterated over, will yield - /// 0, 1, 2, -3 and -4, in turn. - /// - - public static IEnumerable Pad(this IEnumerable source, int width, Func paddingSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (source == null) throw new ArgumentNullException("paddingSelector"); - if (width < 0) throw new ArgumentException(null, "width"); - return PadImpl(source, width, default(TSource), paddingSelector); - } - - private static IEnumerable PadImpl(IEnumerable source, - int width, T padding, Func paddingSelector) - { - Debug.Assert(source != null); - Debug.Assert(width >= 0); - - var count = 0; - foreach (var item in source) - { - yield return item; - count++; - } - while (count < width) - { - yield return paddingSelector != null ? paddingSelector(count) : padding; - count++; - } - } - } +#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; + using System.Diagnostics; + + static partial class MoreEnumerable + { + /// + /// Pads a sequence with default values if it is narrower (shorter + /// in length) than a given width. + /// + /// The type of the elements of . + /// The sequence to pad. + /// The width/length below which to pad. + /// + /// Returns a sequence that is at least as wide/long as the width/length + /// specified by the parameter. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 123, 456, 789 }; + /// IEnumerable<int> result = numbers.Pad(5); + /// + /// The result variable, when iterated over, will yield + /// 123, 456, 789 and two zeroes, in turn. + /// + + public static IEnumerable Pad(this IEnumerable source, int width) + { + return Pad(source, width, default(TSource)); + } + + /// + /// Pads a sequence with a given filler value if it is narrower (shorter + /// in length) than a given width. + /// + /// The type of the elements of . + /// The sequence to pad. + /// The width/length below which to pad. + /// The value to use for padding. + /// + /// Returns a sequence that is at least as wide/long as the width/length + /// specified by the parameter. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 123, 456, 789 }; + /// IEnumerable<int> result = numbers.Pad(5, -1); + /// + /// The result variable, when iterated over, will yield + /// 123, 456, and 789 followed by two occurrences of -1, in turn. + /// + + public static IEnumerable Pad(this IEnumerable source, int width, TSource padding) + { + if (source == null) throw new ArgumentNullException("source"); + if (width < 0) throw new ArgumentException(null, "width"); + return PadImpl(source, width, padding, null); + } + + /// + /// Pads a sequence with a dynamic filler value if it is narrower (shorter + /// in length) than a given width. + /// + /// The type of the elements of . + /// The sequence to pad. + /// The width/length below which to pad. + /// Function to calculate padding. + /// + /// Returns a sequence that is at least as wide/long as the width/length + /// specified by the parameter. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 0, 1, 2 }; + /// IEnumerable<int> result = numbers.Pad(5, i => -i); + /// + /// The result variable, when iterated over, will yield + /// 0, 1, 2, -3 and -4, in turn. + /// + + public static IEnumerable Pad(this IEnumerable source, int width, Func paddingSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (source == null) throw new ArgumentNullException("paddingSelector"); + if (width < 0) throw new ArgumentException(null, "width"); + return PadImpl(source, width, default(TSource), paddingSelector); + } + + private static IEnumerable PadImpl(IEnumerable source, + int width, T padding, Func paddingSelector) + { + Debug.Assert(source != null); + Debug.Assert(width >= 0); + + var count = 0; + foreach (var item in source) + { + yield return item; + count++; + } + while (count < width) + { + yield return paddingSelector != null ? paddingSelector(count) : padding; + count++; + } + } + } } \ No newline at end of file diff --git a/MoreLinq/Pairwise.cs b/MoreLinq/Pairwise.cs index 5c4d7f226..fef607b33 100644 --- a/MoreLinq/Pairwise.cs +++ b/MoreLinq/Pairwise.cs @@ -1,78 +1,78 @@ -#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; - using System.Diagnostics; - - static partial class MoreEnumerable - { - /// - /// Returns a sequence resulting from applying a function to each - /// element in the source sequence and its - /// predecessor, with the exception of the first element which is - /// only returned as the predecessor of the second element. - /// - /// The type of the elements of . - /// The type of the element of the returned sequence. - /// The source sequence. - /// A transform function to apply to - /// each pair of sequence. - /// - /// Returns the resulting sequence. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 123, 456, 789 }; - /// IEnumerable<int> result = numbers.Pairwise(5, (a, b) => a + b); - /// - /// The result variable, when iterated over, will yield - /// 579 and 1245, in turn. - /// - - public static IEnumerable Pairwise(this IEnumerable source, Func resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - return PairwiseImpl(source, resultSelector); - } - - private static IEnumerable PairwiseImpl(this IEnumerable source, Func resultSelector) - { - Debug.Assert(source != null); - Debug.Assert(resultSelector != null); - - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - yield break; - - var previous = e.Current; - while (e.MoveNext()) - { - yield return resultSelector(previous, e.Current); - previous = e.Current; - } - } - } - } +#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; + using System.Diagnostics; + + static partial class MoreEnumerable + { + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// predecessor, with the exception of the first element which is + /// only returned as the predecessor of the second element. + /// + /// The type of the elements of . + /// The type of the element of the returned sequence. + /// The source sequence. + /// A transform function to apply to + /// each pair of sequence. + /// + /// Returns the resulting sequence. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 123, 456, 789 }; + /// IEnumerable<int> result = numbers.Pairwise(5, (a, b) => a + b); + /// + /// The result variable, when iterated over, will yield + /// 579 and 1245, in turn. + /// + + public static IEnumerable Pairwise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return PairwiseImpl(source, resultSelector); + } + + private static IEnumerable PairwiseImpl(this IEnumerable source, Func resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(resultSelector != null); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + yield break; + + var previous = e.Current; + while (e.MoveNext()) + { + yield return resultSelector(previous, e.Current); + previous = e.Current; + } + } + } + } } \ No newline at end of file diff --git a/MoreLinq/Pipe.cs b/MoreLinq/Pipe.cs index e22dafdec..322a4f48d 100644 --- a/MoreLinq/Pipe.cs +++ b/MoreLinq/Pipe.cs @@ -1,56 +1,56 @@ -#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 - { - /// - /// Executes the given action on each element in the source sequence - /// and yields it. - /// - /// - /// The returned sequence is essentially a duplicate of - /// the original, but with the extra action being executed while the - /// sequence is evaluated. The action is always taken before the element - /// is yielded, so any changes made by the action will be visible in the - /// returned sequence. This operator uses deferred execution and streams it results. - /// - /// The type of the elements in the sequence - /// The sequence of elements - /// The action to execute on each element - - public static IEnumerable Pipe(this IEnumerable source, Action action) - { - if (source == null) throw new ArgumentNullException("source"); - if (action == null) throw new ArgumentNullException("action"); - return PipeImpl(source, action); - } - - private static IEnumerable PipeImpl(this IEnumerable source, Action action) - { - foreach (var element in source) - { - action(element); - yield return element; - } - } - } -} +#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 + { + /// + /// Executes the given action on each element in the source sequence + /// and yields it. + /// + /// + /// The returned sequence is essentially a duplicate of + /// the original, but with the extra action being executed while the + /// sequence is evaluated. The action is always taken before the element + /// is yielded, so any changes made by the action will be visible in the + /// returned sequence. This operator uses deferred execution and streams it results. + /// + /// The type of the elements in the sequence + /// The sequence of elements + /// The action to execute on each element + + public static IEnumerable Pipe(this IEnumerable source, Action action) + { + if (source == null) throw new ArgumentNullException("source"); + if (action == null) throw new ArgumentNullException("action"); + return PipeImpl(source, action); + } + + private static IEnumerable PipeImpl(this IEnumerable source, Action action) + { + foreach (var element in source) + { + action(element); + yield return element; + } + } + } +} diff --git a/MoreLinq/PreScan.cs b/MoreLinq/PreScan.cs index 951079d77..e771300ea 100644 --- a/MoreLinq/PreScan.cs +++ b/MoreLinq/PreScan.cs @@ -1,77 +1,77 @@ -#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 - { - /// - /// Performs a pre-scan (exclusive prefix sum) on a sequence of elements. - /// - /// - /// An exclusive prefix sum returns an equal-length sequence where the - /// N-th element is the sum of the first N-1 input elements (the first - /// element is a special case, it is set to the identity). More - /// generally, the pre-scan allows any commutative binary operation, - /// not just a sum. - /// The inclusive version of PreScan is . - /// This operator uses deferred execution and streams its result. - /// - /// - /// - /// Func<int, int, int> plus = (a, b) => a + b; - /// int[] values = { 1, 2, 3, 4 }; - /// IEnumerable<int> prescan = values.PreScan(plus, 0); - /// IEnumerable<int> scan = values.Scan(plus; a + b); - /// IEnumerable<int> result = values.Zip(prescan, plus); - /// - /// prescan will yield { 0, 1, 3, 6 }, while scan - /// and result will both yield { 1, 3, 6, 10 }. This - /// shows the relationship between the inclusive and exclusive prefix sum. - /// - /// Type of elements in source sequence - /// Source sequence - /// Transformation operation - /// Identity element (see remarks) - /// The scanned sequence - - public static IEnumerable PreScan(this IEnumerable source, - Func transformation, TSource identity) - { - if (source == null) throw new ArgumentNullException("source"); - if (transformation == null) throw new ArgumentNullException("transformation"); - return PreScanImpl(source, transformation, identity); - } - - private static IEnumerable PreScanImpl(IEnumerable source, Func f, T id) - { - // special case, the first element is set to the identity - var aggregator = id; - - foreach (var i in source) - { - yield return aggregator; - - // aggregate the next element in the sequence - aggregator = f(aggregator, i); - } - } - } -} +#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 + { + /// + /// Performs a pre-scan (exclusive prefix sum) on a sequence of elements. + /// + /// + /// An exclusive prefix sum returns an equal-length sequence where the + /// N-th element is the sum of the first N-1 input elements (the first + /// element is a special case, it is set to the identity). More + /// generally, the pre-scan allows any commutative binary operation, + /// not just a sum. + /// The inclusive version of PreScan is . + /// This operator uses deferred execution and streams its result. + /// + /// + /// + /// Func<int, int, int> plus = (a, b) => a + b; + /// int[] values = { 1, 2, 3, 4 }; + /// IEnumerable<int> prescan = values.PreScan(plus, 0); + /// IEnumerable<int> scan = values.Scan(plus; a + b); + /// IEnumerable<int> result = values.Zip(prescan, plus); + /// + /// prescan will yield { 0, 1, 3, 6 }, while scan + /// and result will both yield { 1, 3, 6, 10 }. This + /// shows the relationship between the inclusive and exclusive prefix sum. + /// + /// Type of elements in source sequence + /// Source sequence + /// Transformation operation + /// Identity element (see remarks) + /// The scanned sequence + + public static IEnumerable PreScan(this IEnumerable source, + Func transformation, TSource identity) + { + if (source == null) throw new ArgumentNullException("source"); + if (transformation == null) throw new ArgumentNullException("transformation"); + return PreScanImpl(source, transformation, identity); + } + + private static IEnumerable PreScanImpl(IEnumerable source, Func f, T id) + { + // special case, the first element is set to the identity + var aggregator = id; + + foreach (var i in source) + { + yield return aggregator; + + // aggregate the next element in the sequence + aggregator = f(aggregator, i); + } + } + } +} diff --git a/MoreLinq/Prepend.cs b/MoreLinq/Prepend.cs index 93fb03348..6167e24b2 100644 --- a/MoreLinq/Prepend.cs +++ b/MoreLinq/Prepend.cs @@ -1,52 +1,52 @@ -#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 - -using LinqEnumerable = System.Linq.Enumerable; - -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. - /// - /// - /// int[] numbers = { 1, 2, 3 }; - /// IEnumerable<int> result = numbers.Prepend(0); - /// - /// The result variable, when iterated over, will yield - /// 0, 1, 2 and 3, in turn. - - public static IEnumerable Prepend(this IEnumerable source, TSource value) - { - if (source == null) throw new ArgumentNullException("source"); - return LinqEnumerable.Concat(LinqEnumerable.Repeat(value, 1), source); - } - } +#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 + +using LinqEnumerable = System.Linq.Enumerable; + +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. + /// + /// + /// int[] numbers = { 1, 2, 3 }; + /// IEnumerable<int> result = numbers.Prepend(0); + /// + /// The result variable, when iterated over, will yield + /// 0, 1, 2 and 3, in turn. + + public static IEnumerable Prepend(this IEnumerable source, TSource value) + { + if (source == null) throw new ArgumentNullException("source"); + return LinqEnumerable.Concat(LinqEnumerable.Repeat(value, 1), source); + } + } } \ No newline at end of file diff --git a/MoreLinq/Properties/AssemblyInfo.cs b/MoreLinq/Properties/AssemblyInfo.cs index d86d10a1a..972ff9026 100644 --- a/MoreLinq/Properties/AssemblyInfo.cs +++ b/MoreLinq/Properties/AssemblyInfo.cs @@ -1,58 +1,58 @@ -#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 - -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("MoreLINQ")] -[assembly: AssemblyDescription("Extensions to LINQ to Objects")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MoreLINQ")] -[assembly: AssemblyCopyright("Copyright \u00a9 2008 Jonathan Skeet. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Version numbers -// -// The build and revision number reflect the date and time -// of a build, using the follow scheme: -// -// bld = months_since_2000 x 100 + day_of_month -// rev = utc_hours_since_midnight + utc_minutes - -[assembly: AssemblyVersion("1.1.18418.0")] -[assembly: AssemblyFileVersion("1.1.18418.1913")] - -// Debug or release configuration? - -#if DEBUG -[assembly: AssemblyConfiguration("DEBUG")] -#else -[assembly: AssemblyConfiguration("RELEASE")] -#endif - -// CLS compliance and COM visibility - -[assembly: CLSCompliant(true)] -#if !NO_COM -[assembly: ComVisible(false)] - -// ID of the typelib if this project is exposed to COM. - -[assembly: Guid("fc632c9d-390e-4902-8c1c-3e57b08c1d38")] +#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 + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("MoreLINQ")] +[assembly: AssemblyDescription("Extensions to LINQ to Objects")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MoreLINQ")] +[assembly: AssemblyCopyright("Copyright \u00a9 2008 Jonathan Skeet. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version numbers +// +// The build and revision number reflect the date and time +// of a build, using the follow scheme: +// +// bld = months_since_2000 x 100 + day_of_month +// rev = utc_hours_since_midnight + utc_minutes + +[assembly: AssemblyVersion("1.1.18418.0")] +[assembly: AssemblyFileVersion("1.1.18418.1913")] + +// Debug or release configuration? + +#if DEBUG +[assembly: AssemblyConfiguration("DEBUG")] +#else +[assembly: AssemblyConfiguration("RELEASE")] +#endif + +// CLS compliance and COM visibility + +[assembly: CLSCompliant(true)] +#if !NO_COM +[assembly: ComVisible(false)] + +// ID of the typelib if this project is exposed to COM. + +[assembly: Guid("fc632c9d-390e-4902-8c1c-3e57b08c1d38")] #endif \ No newline at end of file diff --git a/MoreLinq/Scan.cs b/MoreLinq/Scan.cs index 61cb64593..0f9491ef7 100644 --- a/MoreLinq/Scan.cs +++ b/MoreLinq/Scan.cs @@ -1,125 +1,125 @@ -#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; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Peforms a scan (inclusive prefix sum) on a sequence of elements. - /// - /// - /// An inclusive prefix sum returns an equal-length sequence where the - /// N-th element is the sum of the first N input elements. More - /// generally, the scan allows any commutative binary operation, not - /// just a sum. - /// The exclusive version of Scan is . - /// This operator uses deferred execution and streams its result. - /// - /// - /// - /// Func<int, int, int> plus = (a, b) => a + b; - /// int[] values = { 1, 2, 3, 4 }; - /// IEnumerable<int> prescan = values.PreScan(plus, 0); - /// IEnumerable<int> scan = values.Scan(plus; a + b); - /// IEnumerable<int> result = values.Zip(prescan, plus); - /// - /// prescan will yield { 0, 1, 3, 6 }, while scan - /// and result will both yield { 1, 3, 6, 10 }. This - /// shows the relationship between the inclusive and exclusive prefix sum. - /// - /// Type of elements in source sequence - /// Source sequence - /// Transformation operation - /// The scanned sequence - /// If is empty. - - public static IEnumerable Scan(this IEnumerable source, - Func transformation) - { - if (source == null) throw new ArgumentNullException("source"); - if (transformation == null) throw new ArgumentNullException("transformation"); - return ScanImpl(source, transformation); - } - - private static IEnumerable ScanImpl(IEnumerable source, Func f) - { - using (var i = source.GetEnumerator()) - { - if (!i.MoveNext()) - throw new InvalidOperationException("Sequence contains no elements."); - - var aggregator = i.Current; - - while (i.MoveNext()) - { - yield return aggregator; - aggregator = f(aggregator, i.Current); - } - yield return aggregator; - } - } - - /// - /// Like except returns - /// the sequence of intermediate results as well as the final one. - /// An additional parameter specifies a seed. - /// - /// - /// This operator uses deferred execution and streams its result. - /// - /// - /// - /// var result = Enumerable.Range(1, 5).Scan(0, (a, b) => a + b); - /// - /// When iterated, result will yield { 0, 1, 3, 6, 10, 15 }. - /// - /// Type of elements in source sequence - /// Type of state - /// Source sequence - /// Initial state to seed - /// Transformation operation - /// The scanned sequence - - public static IEnumerable Scan(this IEnumerable source, - TState seed, Func transformation) - { - if (source == null) throw new ArgumentNullException("source"); - if (transformation == null) throw new ArgumentNullException("transformation"); - return ScanImpl(source, seed, transformation); - } - - private static IEnumerable ScanImpl(IEnumerable source, TState seed, Func f) - { - using (var i = source.GetEnumerator()) - { - var aggregator = seed; - - while (i.MoveNext()) - { - yield return aggregator; - aggregator = f(aggregator, i.Current); - } - yield return aggregator; - } - } - } -} +#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; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Peforms a scan (inclusive prefix sum) on a sequence of elements. + /// + /// + /// An inclusive prefix sum returns an equal-length sequence where the + /// N-th element is the sum of the first N input elements. More + /// generally, the scan allows any commutative binary operation, not + /// just a sum. + /// The exclusive version of Scan is . + /// This operator uses deferred execution and streams its result. + /// + /// + /// + /// Func<int, int, int> plus = (a, b) => a + b; + /// int[] values = { 1, 2, 3, 4 }; + /// IEnumerable<int> prescan = values.PreScan(plus, 0); + /// IEnumerable<int> scan = values.Scan(plus; a + b); + /// IEnumerable<int> result = values.Zip(prescan, plus); + /// + /// prescan will yield { 0, 1, 3, 6 }, while scan + /// and result will both yield { 1, 3, 6, 10 }. This + /// shows the relationship between the inclusive and exclusive prefix sum. + /// + /// Type of elements in source sequence + /// Source sequence + /// Transformation operation + /// The scanned sequence + /// If is empty. + + public static IEnumerable Scan(this IEnumerable source, + Func transformation) + { + if (source == null) throw new ArgumentNullException("source"); + if (transformation == null) throw new ArgumentNullException("transformation"); + return ScanImpl(source, transformation); + } + + private static IEnumerable ScanImpl(IEnumerable source, Func f) + { + using (var i = source.GetEnumerator()) + { + if (!i.MoveNext()) + throw new InvalidOperationException("Sequence contains no elements."); + + var aggregator = i.Current; + + while (i.MoveNext()) + { + yield return aggregator; + aggregator = f(aggregator, i.Current); + } + yield return aggregator; + } + } + + /// + /// Like except returns + /// the sequence of intermediate results as well as the final one. + /// An additional parameter specifies a seed. + /// + /// + /// This operator uses deferred execution and streams its result. + /// + /// + /// + /// var result = Enumerable.Range(1, 5).Scan(0, (a, b) => a + b); + /// + /// When iterated, result will yield { 0, 1, 3, 6, 10, 15 }. + /// + /// Type of elements in source sequence + /// Type of state + /// Source sequence + /// Initial state to seed + /// Transformation operation + /// The scanned sequence + + public static IEnumerable Scan(this IEnumerable source, + TState seed, Func transformation) + { + if (source == null) throw new ArgumentNullException("source"); + if (transformation == null) throw new ArgumentNullException("transformation"); + return ScanImpl(source, seed, transformation); + } + + private static IEnumerable ScanImpl(IEnumerable source, TState seed, Func f) + { + using (var i = source.GetEnumerator()) + { + var aggregator = seed; + + while (i.MoveNext()) + { + yield return aggregator; + aggregator = f(aggregator, i.Current); + } + yield return aggregator; + } + } + } +} diff --git a/MoreLinq/SequenceException.cs b/MoreLinq/SequenceException.cs index 362ae9ec5..f01da3da7 100644 --- a/MoreLinq/SequenceException.cs +++ b/MoreLinq/SequenceException.cs @@ -1,73 +1,73 @@ -#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.Runtime.Serialization; - - /// - /// The exception that is thrown for a sequence that fails a condition. - /// - -#if !NO_EXCEPTION_SERIALIZATION - [ Serializable ] -#endif - public class SequenceException : Exception - { - private const string defaultMessage = "Error in sequence."; - - /// - /// Initializes a new instance of the class. - /// - - public SequenceException() : - this(null) {} - - /// - /// Initializes a new instance of the class - /// with a given error message. - /// - /// A message that describes the error. - - public SequenceException(string message) : - this(message, null) { } - - /// - /// Initializes a new instance of the class - /// with a given error message and a reference to the inner exception - /// that is the cause of the exception. - /// - /// A message that describes the error. - /// The exception that is the cause of the current exception. - - public SequenceException(string message, Exception innerException) : - base(string.IsNullOrEmpty(message) ? defaultMessage : message, innerException) { } - -#if !NO_EXCEPTION_SERIALIZATION - /// - /// Initializes a new instance of the class - /// with serialized data. - /// - /// The object that holds the serialized object data. - /// The contextual information about the source or destination. - - protected SequenceException(SerializationInfo info, StreamingContext context) : - base(info, context) {} -#endif - } -} +#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.Runtime.Serialization; + + /// + /// The exception that is thrown for a sequence that fails a condition. + /// + +#if !NO_EXCEPTION_SERIALIZATION + [ Serializable ] +#endif + public class SequenceException : Exception + { + private const string defaultMessage = "Error in sequence."; + + /// + /// Initializes a new instance of the class. + /// + + public SequenceException() : + this(null) {} + + /// + /// Initializes a new instance of the class + /// with a given error message. + /// + /// A message that describes the error. + + public SequenceException(string message) : + this(message, null) { } + + /// + /// Initializes a new instance of the class + /// with a given error message and a reference to the inner exception + /// that is the cause of the exception. + /// + /// A message that describes the error. + /// The exception that is the cause of the current exception. + + public SequenceException(string message, Exception innerException) : + base(string.IsNullOrEmpty(message) ? defaultMessage : message, innerException) { } + +#if !NO_EXCEPTION_SERIALIZATION + /// + /// Initializes a new instance of the class + /// with serialized data. + /// + /// The object that holds the serialized object data. + /// The contextual information about the source or destination. + + protected SequenceException(SerializationInfo info, StreamingContext context) : + base(info, context) {} +#endif + } +} diff --git a/MoreLinq/SingleOrFallback.cs b/MoreLinq/SingleOrFallback.cs index 4369d4993..84f714826 100644 --- a/MoreLinq/SingleOrFallback.cs +++ b/MoreLinq/SingleOrFallback.cs @@ -1,90 +1,90 @@ -#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 single element in the given sequence, or the result - /// of executing a fallback delegate if the sequence is empty. - /// This method throws an exception if there is more than one element in the sequence. - /// - /// - /// The fallback delegate is not executed if the sequence is non-empty. - /// This operator uses immediate execution and has optimizations for sources. - /// - /// Element type of sequence - /// The source sequence - /// The fallback delegate to execute if the sequence is empty - /// source or fallback is null - /// The sequence has more than one element - /// The single element in the sequence, or the result of calling the - /// fallback delegate if the sequence is empty. - /// - /// - /// var numbers = { 123, 456, 789 }; - /// var result = numbers.Where(x => x == 100).SingleOrFallback(() => -1); - /// - /// The result variable will contain -1. - /// - - public static TSource SingleOrFallback(this IEnumerable source, Func fallback) - { - if (source == null) throw new ArgumentNullException("source"); - if (fallback == null) throw new ArgumentNullException("fallback"); - - var list = source as IList; - if (list != null) - { - switch (list.Count) - { - case 0: - return fallback(); - - case 1: - return list[0]; - - // anything but 0 and 1 is not handled - } - } - else - { - using (var iterator = source.GetEnumerator()) - { - if (!iterator.MoveNext()) - { - return fallback(); - } - var first = iterator.Current; - - // Return if there's no next element - if (!iterator.MoveNext()) - { - return first; - } - } - } - - // We should have checked the sequence length and returned by now - throw new InvalidOperationException("Sequence contains more than one element"); - } - } -} +#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 single element in the given sequence, or the result + /// of executing a fallback delegate if the sequence is empty. + /// This method throws an exception if there is more than one element in the sequence. + /// + /// + /// The fallback delegate is not executed if the sequence is non-empty. + /// This operator uses immediate execution and has optimizations for sources. + /// + /// Element type of sequence + /// The source sequence + /// The fallback delegate to execute if the sequence is empty + /// source or fallback is null + /// The sequence has more than one element + /// The single element in the sequence, or the result of calling the + /// fallback delegate if the sequence is empty. + /// + /// + /// var numbers = { 123, 456, 789 }; + /// var result = numbers.Where(x => x == 100).SingleOrFallback(() => -1); + /// + /// The result variable will contain -1. + /// + + public static TSource SingleOrFallback(this IEnumerable source, Func fallback) + { + if (source == null) throw new ArgumentNullException("source"); + if (fallback == null) throw new ArgumentNullException("fallback"); + + var list = source as IList; + if (list != null) + { + switch (list.Count) + { + case 0: + return fallback(); + + case 1: + return list[0]; + + // anything but 0 and 1 is not handled + } + } + else + { + using (var iterator = source.GetEnumerator()) + { + if (!iterator.MoveNext()) + { + return fallback(); + } + var first = iterator.Current; + + // Return if there's no next element + if (!iterator.MoveNext()) + { + return first; + } + } + } + + // We should have checked the sequence length and returned by now + throw new InvalidOperationException("Sequence contains more than one element"); + } + } +} diff --git a/MoreLinq/SkipUntil.cs b/MoreLinq/SkipUntil.cs index 740639a6d..334d0e2a9 100644 --- a/MoreLinq/SkipUntil.cs +++ b/MoreLinq/SkipUntil.cs @@ -1,80 +1,80 @@ -#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 - { - /// - /// Skips items from the input sequence until the given predicate returns true - /// when applied to the current source item; that item will be the last skipped. - /// - /// - /// - /// SkipUntil differs from Enumerable.SkipWhile in two respects. Firstly, the sense - /// of the predicate is reversed: it is expected that the predicate will return false - /// to start with, and then return true - for example, when trying to find a matching - /// item in a sequence. - /// - /// - /// Secondly, SkipUntil skips the element which causes the predicate to return true. For - /// example, in a sequence { 1, 2, 3, 4, 5 } and with a predicate of - /// x => x == 3, the result would be { 4, 5 }. - /// - /// - /// SkipUntil is as lazy as possible: it will not iterate over the source sequence - /// until it has to, it won't iterate further than it has to, and it won't evaluate - /// the predicate until it has to. (This means that an item may be returned which would - /// actually cause the predicate to throw an exception if it were evaluated, so long as - /// it comes after the first item causing the predicate to return true.) - /// - /// - /// Type of the source sequence - /// Source sequence - /// Predicate used to determine when to stop yielding results from the source. - /// Items from the source sequence after the predicate first returns true when applied to the item. - /// or is null - - public static IEnumerable SkipUntil(this IEnumerable source, Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - return SkipUntilImpl(source, predicate); - } - - private static IEnumerable SkipUntilImpl(this IEnumerable source, Func predicate) - { - using (var iterator = source.GetEnumerator()) - { - while (iterator.MoveNext()) - { - if (predicate(iterator.Current)) - { - break; - } - } - while (iterator.MoveNext()) - { - yield return iterator.Current; - } - } - } - } -} +#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 + { + /// + /// Skips items from the input sequence until the given predicate returns true + /// when applied to the current source item; that item will be the last skipped. + /// + /// + /// + /// SkipUntil differs from Enumerable.SkipWhile in two respects. Firstly, the sense + /// of the predicate is reversed: it is expected that the predicate will return false + /// to start with, and then return true - for example, when trying to find a matching + /// item in a sequence. + /// + /// + /// Secondly, SkipUntil skips the element which causes the predicate to return true. For + /// example, in a sequence { 1, 2, 3, 4, 5 } and with a predicate of + /// x => x == 3, the result would be { 4, 5 }. + /// + /// + /// SkipUntil is as lazy as possible: it will not iterate over the source sequence + /// until it has to, it won't iterate further than it has to, and it won't evaluate + /// the predicate until it has to. (This means that an item may be returned which would + /// actually cause the predicate to throw an exception if it were evaluated, so long as + /// it comes after the first item causing the predicate to return true.) + /// + /// + /// Type of the source sequence + /// Source sequence + /// Predicate used to determine when to stop yielding results from the source. + /// Items from the source sequence after the predicate first returns true when applied to the item. + /// or is null + + public static IEnumerable SkipUntil(this IEnumerable source, Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + return SkipUntilImpl(source, predicate); + } + + private static IEnumerable SkipUntilImpl(this IEnumerable source, Func predicate) + { + using (var iterator = source.GetEnumerator()) + { + while (iterator.MoveNext()) + { + if (predicate(iterator.Current)) + { + break; + } + } + while (iterator.MoveNext()) + { + yield return iterator.Current; + } + } + } + } +} diff --git a/MoreLinq/Split.cs b/MoreLinq/Split.cs index 5428e72d4..a2cbe73c0 100644 --- a/MoreLinq/Split.cs +++ b/MoreLinq/Split.cs @@ -1,224 +1,224 @@ -#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; - using System.Diagnostics; - using System.Linq; - - static partial class MoreEnumerable - { - - /// - /// Splits the source sequence by a separator. - /// - - public static IEnumerable> Split(this IEnumerable source, - TSource separator) - { - return Split(source, separator, int.MaxValue); - } - - /// - /// Splits the source sequence by a separator given a maximum count of splits. - /// - - public static IEnumerable> Split(this IEnumerable source, - TSource separator, int count) - { - return Split(source, separator, count, s => s); - } - - /// - /// Splits the source sequence by a separator and then transforms - /// the splits into results. - /// - - public static IEnumerable Split(this IEnumerable source, - TSource separator, - Func, TResult> resultSelector) - { - return Split(source, separator, int.MaxValue, resultSelector); - } - - /// - /// Splits the source sequence by a separator, given a maximum count - /// of splits, and then transforms the splits into results. - /// - - public static IEnumerable Split(this IEnumerable source, - TSource separator, int count, - Func, TResult> resultSelector) - { - return Split(source, separator, null, count, resultSelector); - } - - /// - /// Splits the source sequence by a separator and then transforms the - /// splits into results. - /// - - public static IEnumerable> Split(this IEnumerable source, - TSource separator, IEqualityComparer comparer) - { - return Split(source, separator, comparer, int.MaxValue); - } - - /// - /// Splits the source sequence by a separator, given a maximum count - /// of splits. A parameter specifies how the separator is compared - /// for equality. - /// - - public static IEnumerable> Split(this IEnumerable source, - TSource separator, IEqualityComparer comparer, int count) - { - return Split(source, separator, comparer, count, s => s); - } - - /// - /// Splits the source sequence by a separator and then transforms the - /// splits into results. A parameter specifies how the separator is - /// compared for equality. - /// - - public static IEnumerable Split(this IEnumerable source, - TSource separator, IEqualityComparer comparer, - Func, TResult> resultSelector) - { - return Split(source, separator, comparer, int.MaxValue, resultSelector); - } - - /// - /// Splits the source sequence by a separator, given a maximum count - /// of splits, and then transforms the splits into results. A - /// parameter specifies how the separator is compared for equality. - /// - - public static IEnumerable Split(this IEnumerable source, - TSource separator, IEqualityComparer comparer, int count, - Func, TResult> resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (count <= 0) throw new ArgumentOutOfRangeException("count"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - return SplitImpl(source, separator, comparer ?? EqualityComparer.Default, count, resultSelector); - } - - private static IEnumerable SplitImpl(IEnumerable source, - TSource separator, IEqualityComparer comparer, int count, - Func, TResult> resultSelector) - { - Debug.Assert(source != null); - Debug.Assert(comparer != null); - Debug.Assert(count >= 0); - Debug.Assert(resultSelector != null); - - return Split(source, item => comparer.Equals(item, separator), count, resultSelector); - } - - /// - /// Splits the source sequence by a separator function. - /// - - public static IEnumerable> Split(this IEnumerable source, - Func separatorFunc) - { - return Split(source, separatorFunc, int.MaxValue); - } - - /// - /// Splits the source sequence by a separator function, given a - /// maximum count of splits. - /// - - public static IEnumerable> Split(this IEnumerable source, - Func separatorFunc, int count) - { - return Split(source, separatorFunc, count, s => s); - } - - /// - /// Splits the source sequence by a separator function and then - /// transforms the splits into results. - /// - - public static IEnumerable Split(this IEnumerable source, - Func separatorFunc, - Func, TResult> resultSelector) - { - return Split(source, separatorFunc, int.MaxValue, resultSelector); - } - - /// - /// Splits the source sequence by a separator function, given a - /// maximum count of splits, and then transforms the splits into results. - /// - - public static IEnumerable Split(this IEnumerable source, - Func separatorFunc, int count, - Func, TResult> resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (source == null) throw new ArgumentNullException("separatorFunc"); - if (count <= 0) throw new ArgumentOutOfRangeException("count"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - return SplitImpl(source, separatorFunc, count, resultSelector); - } - - private static IEnumerable SplitImpl(IEnumerable source, - Func separatorFunc, int count, - Func, TResult> resultSelector) - { - Debug.Assert(source != null); - Debug.Assert(separatorFunc != null); - Debug.Assert(count >= 0); - Debug.Assert(resultSelector != null); - - if (count == 0) // No splits? - { - yield return resultSelector(source); - } - else - { - List items = null; - - foreach (var item in source) - { - if (count > 0 && separatorFunc(item)) - { - yield return resultSelector(items ?? Enumerable.Empty()); - count--; - items = null; - } - else - { - if (items == null) - items = new List(); - - items.Add(item); - } - } - - if (items != null && items.Count > 0) - yield return resultSelector(items); - } - } - } -} +#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; + using System.Diagnostics; + using System.Linq; + + static partial class MoreEnumerable + { + + /// + /// Splits the source sequence by a separator. + /// + + public static IEnumerable> Split(this IEnumerable source, + TSource separator) + { + return Split(source, separator, int.MaxValue); + } + + /// + /// Splits the source sequence by a separator given a maximum count of splits. + /// + + public static IEnumerable> Split(this IEnumerable source, + TSource separator, int count) + { + return Split(source, separator, count, s => s); + } + + /// + /// Splits the source sequence by a separator and then transforms + /// the splits into results. + /// + + public static IEnumerable Split(this IEnumerable source, + TSource separator, + Func, TResult> resultSelector) + { + return Split(source, separator, int.MaxValue, resultSelector); + } + + /// + /// Splits the source sequence by a separator, given a maximum count + /// of splits, and then transforms the splits into results. + /// + + public static IEnumerable Split(this IEnumerable source, + TSource separator, int count, + Func, TResult> resultSelector) + { + return Split(source, separator, null, count, resultSelector); + } + + /// + /// Splits the source sequence by a separator and then transforms the + /// splits into results. + /// + + public static IEnumerable> Split(this IEnumerable source, + TSource separator, IEqualityComparer comparer) + { + return Split(source, separator, comparer, int.MaxValue); + } + + /// + /// Splits the source sequence by a separator, given a maximum count + /// of splits. A parameter specifies how the separator is compared + /// for equality. + /// + + public static IEnumerable> Split(this IEnumerable source, + TSource separator, IEqualityComparer comparer, int count) + { + return Split(source, separator, comparer, count, s => s); + } + + /// + /// Splits the source sequence by a separator and then transforms the + /// splits into results. A parameter specifies how the separator is + /// compared for equality. + /// + + public static IEnumerable Split(this IEnumerable source, + TSource separator, IEqualityComparer comparer, + Func, TResult> resultSelector) + { + return Split(source, separator, comparer, int.MaxValue, resultSelector); + } + + /// + /// Splits the source sequence by a separator, given a maximum count + /// of splits, and then transforms the splits into results. A + /// parameter specifies how the separator is compared for equality. + /// + + public static IEnumerable Split(this IEnumerable source, + TSource separator, IEqualityComparer comparer, int count, + Func, TResult> resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (count <= 0) throw new ArgumentOutOfRangeException("count"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return SplitImpl(source, separator, comparer ?? EqualityComparer.Default, count, resultSelector); + } + + private static IEnumerable SplitImpl(IEnumerable source, + TSource separator, IEqualityComparer comparer, int count, + Func, TResult> resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(comparer != null); + Debug.Assert(count >= 0); + Debug.Assert(resultSelector != null); + + return Split(source, item => comparer.Equals(item, separator), count, resultSelector); + } + + /// + /// Splits the source sequence by a separator function. + /// + + public static IEnumerable> Split(this IEnumerable source, + Func separatorFunc) + { + return Split(source, separatorFunc, int.MaxValue); + } + + /// + /// Splits the source sequence by a separator function, given a + /// maximum count of splits. + /// + + public static IEnumerable> Split(this IEnumerable source, + Func separatorFunc, int count) + { + return Split(source, separatorFunc, count, s => s); + } + + /// + /// Splits the source sequence by a separator function and then + /// transforms the splits into results. + /// + + public static IEnumerable Split(this IEnumerable source, + Func separatorFunc, + Func, TResult> resultSelector) + { + return Split(source, separatorFunc, int.MaxValue, resultSelector); + } + + /// + /// Splits the source sequence by a separator function, given a + /// maximum count of splits, and then transforms the splits into results. + /// + + public static IEnumerable Split(this IEnumerable source, + Func separatorFunc, int count, + Func, TResult> resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (source == null) throw new ArgumentNullException("separatorFunc"); + if (count <= 0) throw new ArgumentOutOfRangeException("count"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return SplitImpl(source, separatorFunc, count, resultSelector); + } + + private static IEnumerable SplitImpl(IEnumerable source, + Func separatorFunc, int count, + Func, TResult> resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(separatorFunc != null); + Debug.Assert(count >= 0); + Debug.Assert(resultSelector != null); + + if (count == 0) // No splits? + { + yield return resultSelector(source); + } + else + { + List items = null; + + foreach (var item in source) + { + if (count > 0 && separatorFunc(item)) + { + yield return resultSelector(items ?? Enumerable.Empty()); + count--; + items = null; + } + else + { + if (items == null) + items = new List(); + + items.Add(item); + } + } + + if (items != null && items.Count > 0) + yield return resultSelector(items); + } + } + } +} diff --git a/MoreLinq/TakeEvery.cs b/MoreLinq/TakeEvery.cs index 3ccd3ef52..2fe9c17aa 100644 --- a/MoreLinq/TakeEvery.cs +++ b/MoreLinq/TakeEvery.cs @@ -1,50 +1,50 @@ -#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; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Returns every N-th element of a source sequence. - /// - /// Type of the source sequence - /// Source sequence - /// Number of elements to bypass before returning the next element. - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 1, 2, 3, 4, 5 }; - /// IEnumerable<int> result = numbers.TakeEvery(2); - /// - /// The result variable, when iterated over, will yield 1, 3 and 5, in turn. - /// - - public static IEnumerable TakeEvery(this IEnumerable source, int step) - { - if (source == null) throw new ArgumentNullException("source"); - if (step <= 0) throw new ArgumentOutOfRangeException("step"); - return source.Where((e, i) => i % step == 0); - } - } -} +#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; + using System.Linq; + + static partial class MoreEnumerable + { + /// + /// Returns every N-th element of a source sequence. + /// + /// Type of the source sequence + /// Source sequence + /// Number of elements to bypass before returning the next element. + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 1, 2, 3, 4, 5 }; + /// IEnumerable<int> result = numbers.TakeEvery(2); + /// + /// The result variable, when iterated over, will yield 1, 3 and 5, in turn. + /// + + public static IEnumerable TakeEvery(this IEnumerable source, int step) + { + if (source == null) throw new ArgumentNullException("source"); + if (step <= 0) throw new ArgumentOutOfRangeException("step"); + return source.Where((e, i) => i % step == 0); + } + } +} diff --git a/MoreLinq/TakeLast.cs b/MoreLinq/TakeLast.cs index 5a80d3f58..0e6a39103 100644 --- a/MoreLinq/TakeLast.cs +++ b/MoreLinq/TakeLast.cs @@ -1,75 +1,75 @@ -#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; - using System.Diagnostics; - - static partial class MoreEnumerable - { - /// - /// Returns a specified number of contiguous elements from the end of - /// a sequence. - /// - /// The type of the elements of . - /// The sequence to return the last element of. - /// The number of elements to return. - /// - /// An that contains the specified number of - /// elements from the end of the input sequence. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 12, 34, 56, 78 }; - /// IEnumerable<int> result = numbers.TakeLast(2); - /// - /// The result variable, when iterated over, will yield - /// 56 and 78 in turn. - /// - - public static IEnumerable TakeLast(this IEnumerable source, int count) - { - if (source == null) throw new ArgumentNullException("source"); - return TakeLastImpl(source, count); - } - - private static IEnumerable TakeLastImpl(IEnumerable source, int count) - { - Debug.Assert(source != null); - - if (count <= 0) - yield break; - - var q = new Queue(count); - - foreach (var item in source) - { - if (q.Count == count) - q.Dequeue(); - q.Enqueue(item); - } - - foreach (var item in q) - yield return item; - } - } +#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; + using System.Diagnostics; + + static partial class MoreEnumerable + { + /// + /// Returns a specified number of contiguous elements from the end of + /// a sequence. + /// + /// The type of the elements of . + /// The sequence to return the last element of. + /// The number of elements to return. + /// + /// An that contains the specified number of + /// elements from the end of the input sequence. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 12, 34, 56, 78 }; + /// IEnumerable<int> result = numbers.TakeLast(2); + /// + /// The result variable, when iterated over, will yield + /// 56 and 78 in turn. + /// + + public static IEnumerable TakeLast(this IEnumerable source, int count) + { + if (source == null) throw new ArgumentNullException("source"); + return TakeLastImpl(source, count); + } + + private static IEnumerable TakeLastImpl(IEnumerable source, int count) + { + Debug.Assert(source != null); + + if (count <= 0) + yield break; + + var q = new Queue(count); + + foreach (var item in source) + { + if (q.Count == count) + q.Dequeue(); + q.Enqueue(item); + } + + foreach (var item in q) + yield return item; + } + } } \ No newline at end of file diff --git a/MoreLinq/TakeUntil.cs b/MoreLinq/TakeUntil.cs index 56d8ec250..7db00c873 100644 --- a/MoreLinq/TakeUntil.cs +++ b/MoreLinq/TakeUntil.cs @@ -1,74 +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 items from the input sequence until the given predicate returns true - /// when applied to the current source item; that item will be the last returned. - /// - /// - /// - /// TakeUntil differs from Enumerable.TakeWhile in two respects. Firstly, the sense - /// of the predicate is reversed: it is expected that the predicate will return false - /// to start with, and then return true - for example, when trying to find a matching - /// item in a sequence. - /// - /// - /// Secondly, TakeUntil yields the element which causes the predicate to return true. For - /// example, in a sequence { 1, 2, 3, 4, 5 } and with a predicate of - /// x => x == 3, the result would be { 1, 2, 3 }. - /// - /// - /// TakeUntil is as lazy as possible: it will not iterate over the source sequence - /// until it has to, it won't iterate further than it has to, and it won't evaluate - /// the predicate until it has to. (This means that an item may be returned which would - /// actually cause the predicate to throw an exception if it were evaluated, so long as - /// no more items of data are requested.) - /// - /// - /// Type of the source sequence - /// Source sequence - /// Predicate used to determine when to stop yielding results from the source. - /// Items from the source sequence, until the predicate returns true when applied to the item. - /// or is null - - public static IEnumerable TakeUntil(this IEnumerable source, Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - return TakeUntilImpl(source, predicate); - } - - private static IEnumerable TakeUntilImpl(this IEnumerable source, Func predicate) - { - foreach (var item in source) - { - yield return item; - if (predicate(item)) - { - yield break; - } - } - } - } -} +#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 items from the input sequence until the given predicate returns true + /// when applied to the current source item; that item will be the last returned. + /// + /// + /// + /// TakeUntil differs from Enumerable.TakeWhile in two respects. Firstly, the sense + /// of the predicate is reversed: it is expected that the predicate will return false + /// to start with, and then return true - for example, when trying to find a matching + /// item in a sequence. + /// + /// + /// Secondly, TakeUntil yields the element which causes the predicate to return true. For + /// example, in a sequence { 1, 2, 3, 4, 5 } and with a predicate of + /// x => x == 3, the result would be { 1, 2, 3 }. + /// + /// + /// TakeUntil is as lazy as possible: it will not iterate over the source sequence + /// until it has to, it won't iterate further than it has to, and it won't evaluate + /// the predicate until it has to. (This means that an item may be returned which would + /// actually cause the predicate to throw an exception if it were evaluated, so long as + /// no more items of data are requested.) + /// + /// + /// Type of the source sequence + /// Source sequence + /// Predicate used to determine when to stop yielding results from the source. + /// Items from the source sequence, until the predicate returns true when applied to the item. + /// or is null + + public static IEnumerable TakeUntil(this IEnumerable source, Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + return TakeUntilImpl(source, predicate); + } + + private static IEnumerable TakeUntilImpl(this IEnumerable source, Func predicate) + { + foreach (var item in source) + { + yield return item; + if (predicate(item)) + { + yield break; + } + } + } + } +} diff --git a/MoreLinq/ToDataTable.cs b/MoreLinq/ToDataTable.cs index 4a04ce436..327a0588e 100644 --- a/MoreLinq/ToDataTable.cs +++ b/MoreLinq/ToDataTable.cs @@ -1,267 +1,267 @@ -#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; - using System.Data; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - - static partial class MoreEnumerable - { - private static MemberInfo GetAccessedMember(LambdaExpression lambda) - { - var body = lambda.Body; - - // If it's a field access, boxing was used, we need the field - if ((body.NodeType == ExpressionType.Convert) || (body.NodeType == ExpressionType.ConvertChecked)) - { - body = ((UnaryExpression)body).Operand; - } - - // Check if the MemberExpression is valid and is a "first level" member access e.g. not a.b.c - var memberExpression = body as MemberExpression; - if ((memberExpression == null) || (memberExpression.Expression.NodeType != ExpressionType.Parameter)) - { - throw new ArgumentException(string.Format("Illegal expression: {0}", lambda), "lambda"); - } - - return memberExpression.Member; - } - - private static IEnumerable PrepareMemberInfos(ICollection>> expressions) - { - // - // If no lambda expressions supplied then reflect them off the source element type. - // - - if (expressions == null || expressions.Count == 0) - { - return from m in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance) - where m.MemberType == MemberTypes.Field - || (m.MemberType == MemberTypes.Property && ((PropertyInfo) m).GetIndexParameters().Length == 0) - select m; - } - - // - // Ensure none of the expressions is null. - // - - if (expressions.Any(e => e == null)) - throw new ArgumentException("One of the supplied expressions was null.", "expressions"); - - try - { - return expressions.Select(GetAccessedMember); - } - catch (ArgumentException e) - { - throw new ArgumentException("One of the supplied expressions is not allowed.", "expressions", e); - } - } - - /// - /// The resulting array may contain null entries and those represent - /// columns for which there is no source member supplying a value. - /// - - private static MemberInfo[] BuildOrBindSchema(DataTable table, MemberInfo[] members) - { - // - // Retrieve member information needed to - // build or validate the table schema. - // - - var columns = table.Columns; - - var schemas = from m in members - let type = m.MemberType == MemberTypes.Property - ? ((PropertyInfo) m).PropertyType - : ((FieldInfo) m).FieldType - select new - { - Member = m, - Type = type.IsGenericType - && typeof(Nullable<>) == type.GetGenericTypeDefinition() - ? type.GetGenericArguments()[0] - : type, - Column = columns[m.Name], - }; - - // - // If the table has no columns then build the schema. - // If it has columns then validate members against the columns - // and re-order members to be aligned with column ordering. - // - - if (columns.Count == 0) - { - columns.AddRange(schemas.Select(m => new DataColumn(m.Member.Name, m.Type)).ToArray()); - } - else - { - members = new MemberInfo[columns.Count]; - - foreach (var info in schemas) - { - var member = info.Member; - var column = info.Column; - - if (column == null) - throw new ArgumentException(string.Format("Column named '{0}' is missing.", member.Name), "table"); - - if (info.Type != column.DataType) - throw new ArgumentException(string.Format("Column named '{0}' has wrong data type. It should be {1} when it is {2}.", member.Name, info.Type, column.DataType), "table"); - - members[column.Ordinal] = member; - } - } - - return members; - } - - private static UnaryExpression CreateMemberAccessor(Expression parameter, MemberInfo member) - { - var access = Expression.MakeMemberAccess(parameter, member); - return Expression.Convert(access, typeof(object)); - } - - private static Func CreateShredder(IEnumerable members) - { - var parameter = Expression.Parameter(typeof(T), "e"); - - // - // It is valid for members sequence to have null entries, in - // which case a null constant is emitted into the corresponding - // row values array. - // - - var initializers = members.Select(m => m != null - ? (Expression)CreateMemberAccessor(parameter, m) - : Expression.Constant(null, typeof(object))); - - var array = Expression.NewArrayInit(typeof(object), initializers); - - var lambda = Expression.Lambda>(array, parameter); - - return lambda.Compile(); - } - - /// - /// Appends elements in the sequence as rows of a given - /// object with a set of lambda expressions specifying which members (property - /// or field) of each element in the sequence will supply the column values. - /// - /// The type of the elements of . - /// The type of the input and resulting object. - /// The source. - /// The type of object where to add rows - /// Expressions providing access to element members. - /// - /// A or subclass representing the source. - /// - /// This operator uses immediate execution. - - public static TTable ToDataTable(this IEnumerable source, TTable table, params Expression>[] expressions) - where TTable : DataTable - { - if (source == null) throw new ArgumentNullException("source"); - if (table == null) throw new ArgumentNullException("table"); - - var members = PrepareMemberInfos(expressions).ToArray(); - members = BuildOrBindSchema(table, members); - var shredder = CreateShredder(members); - - // - // Builds rows out of elements in the sequence and - // add them to the table. - // - - table.BeginLoadData(); - - try - { - foreach (var element in source) - { - var row = table.NewRow(); - row.ItemArray = shredder(element); - table.Rows.Add(row); - } - } - finally - { - table.EndLoadData(); - } - - return table; - } - - /// - /// Appends elements in the sequence as rows of a given object. - /// - /// The type of the elements of . - /// - /// The source. - /// - /// - /// A or subclass representing the source. - /// - /// This operator uses immediate execution. - - public static TTable ToDataTable(this IEnumerable source, TTable table) - where TTable : DataTable - { - return ToDataTable(source, table, null); - } - - /// - /// Appends elements in the sequence as rows of a given - /// object with a set of lambda expressions specifying which members (property - /// or field) of each element in the sequence will supply the column values. - /// - /// The type of the elements of . - /// The source. - /// Expressions providing access to element members. - /// - /// A representing the source. - /// - /// This operator uses immediate execution. - - public static DataTable ToDataTable(this IEnumerable source, params Expression>[] expressions) - { - return ToDataTable(source, new DataTable(), expressions); - } - - /// - /// Converts a sequence to a object. - /// - /// The type of the elements of . - /// The source. - /// - /// A representing the source. - /// - /// This operator uses immediate execution. - - public static DataTable ToDataTable(this IEnumerable source) - { - return ToDataTable(source, new DataTable()); - } - } -} +#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; + using System.Data; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + + static partial class MoreEnumerable + { + private static MemberInfo GetAccessedMember(LambdaExpression lambda) + { + var body = lambda.Body; + + // If it's a field access, boxing was used, we need the field + if ((body.NodeType == ExpressionType.Convert) || (body.NodeType == ExpressionType.ConvertChecked)) + { + body = ((UnaryExpression)body).Operand; + } + + // Check if the MemberExpression is valid and is a "first level" member access e.g. not a.b.c + var memberExpression = body as MemberExpression; + if ((memberExpression == null) || (memberExpression.Expression.NodeType != ExpressionType.Parameter)) + { + throw new ArgumentException(string.Format("Illegal expression: {0}", lambda), "lambda"); + } + + return memberExpression.Member; + } + + private static IEnumerable PrepareMemberInfos(ICollection>> expressions) + { + // + // If no lambda expressions supplied then reflect them off the source element type. + // + + if (expressions == null || expressions.Count == 0) + { + return from m in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance) + where m.MemberType == MemberTypes.Field + || (m.MemberType == MemberTypes.Property && ((PropertyInfo) m).GetIndexParameters().Length == 0) + select m; + } + + // + // Ensure none of the expressions is null. + // + + if (expressions.Any(e => e == null)) + throw new ArgumentException("One of the supplied expressions was null.", "expressions"); + + try + { + return expressions.Select(GetAccessedMember); + } + catch (ArgumentException e) + { + throw new ArgumentException("One of the supplied expressions is not allowed.", "expressions", e); + } + } + + /// + /// The resulting array may contain null entries and those represent + /// columns for which there is no source member supplying a value. + /// + + private static MemberInfo[] BuildOrBindSchema(DataTable table, MemberInfo[] members) + { + // + // Retrieve member information needed to + // build or validate the table schema. + // + + var columns = table.Columns; + + var schemas = from m in members + let type = m.MemberType == MemberTypes.Property + ? ((PropertyInfo) m).PropertyType + : ((FieldInfo) m).FieldType + select new + { + Member = m, + Type = type.IsGenericType + && typeof(Nullable<>) == type.GetGenericTypeDefinition() + ? type.GetGenericArguments()[0] + : type, + Column = columns[m.Name], + }; + + // + // If the table has no columns then build the schema. + // If it has columns then validate members against the columns + // and re-order members to be aligned with column ordering. + // + + if (columns.Count == 0) + { + columns.AddRange(schemas.Select(m => new DataColumn(m.Member.Name, m.Type)).ToArray()); + } + else + { + members = new MemberInfo[columns.Count]; + + foreach (var info in schemas) + { + var member = info.Member; + var column = info.Column; + + if (column == null) + throw new ArgumentException(string.Format("Column named '{0}' is missing.", member.Name), "table"); + + if (info.Type != column.DataType) + throw new ArgumentException(string.Format("Column named '{0}' has wrong data type. It should be {1} when it is {2}.", member.Name, info.Type, column.DataType), "table"); + + members[column.Ordinal] = member; + } + } + + return members; + } + + private static UnaryExpression CreateMemberAccessor(Expression parameter, MemberInfo member) + { + var access = Expression.MakeMemberAccess(parameter, member); + return Expression.Convert(access, typeof(object)); + } + + private static Func CreateShredder(IEnumerable members) + { + var parameter = Expression.Parameter(typeof(T), "e"); + + // + // It is valid for members sequence to have null entries, in + // which case a null constant is emitted into the corresponding + // row values array. + // + + var initializers = members.Select(m => m != null + ? (Expression)CreateMemberAccessor(parameter, m) + : Expression.Constant(null, typeof(object))); + + var array = Expression.NewArrayInit(typeof(object), initializers); + + var lambda = Expression.Lambda>(array, parameter); + + return lambda.Compile(); + } + + /// + /// Appends elements in the sequence as rows of a given + /// object with a set of lambda expressions specifying which members (property + /// or field) of each element in the sequence will supply the column values. + /// + /// The type of the elements of . + /// The type of the input and resulting object. + /// The source. + /// The type of object where to add rows + /// Expressions providing access to element members. + /// + /// A or subclass representing the source. + /// + /// This operator uses immediate execution. + + public static TTable ToDataTable(this IEnumerable source, TTable table, params Expression>[] expressions) + where TTable : DataTable + { + if (source == null) throw new ArgumentNullException("source"); + if (table == null) throw new ArgumentNullException("table"); + + var members = PrepareMemberInfos(expressions).ToArray(); + members = BuildOrBindSchema(table, members); + var shredder = CreateShredder(members); + + // + // Builds rows out of elements in the sequence and + // add them to the table. + // + + table.BeginLoadData(); + + try + { + foreach (var element in source) + { + var row = table.NewRow(); + row.ItemArray = shredder(element); + table.Rows.Add(row); + } + } + finally + { + table.EndLoadData(); + } + + return table; + } + + /// + /// Appends elements in the sequence as rows of a given object. + /// + /// The type of the elements of . + /// + /// The source. + /// + /// + /// A or subclass representing the source. + /// + /// This operator uses immediate execution. + + public static TTable ToDataTable(this IEnumerable source, TTable table) + where TTable : DataTable + { + return ToDataTable(source, table, null); + } + + /// + /// Appends elements in the sequence as rows of a given + /// object with a set of lambda expressions specifying which members (property + /// or field) of each element in the sequence will supply the column values. + /// + /// The type of the elements of . + /// The source. + /// Expressions providing access to element members. + /// + /// A representing the source. + /// + /// This operator uses immediate execution. + + public static DataTable ToDataTable(this IEnumerable source, params Expression>[] expressions) + { + return ToDataTable(source, new DataTable(), expressions); + } + + /// + /// Converts a sequence to a object. + /// + /// The type of the elements of . + /// The source. + /// + /// A representing the source. + /// + /// This operator uses immediate execution. + + public static DataTable ToDataTable(this IEnumerable source) + { + return ToDataTable(source, new DataTable()); + } + } +} diff --git a/MoreLinq/ToDelimitedString.cs b/MoreLinq/ToDelimitedString.cs index c0c8f2b4a..b19e4bd10 100644 --- a/MoreLinq/ToDelimitedString.cs +++ b/MoreLinq/ToDelimitedString.cs @@ -1,81 +1,81 @@ -#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; - using System.Diagnostics; - using System.Globalization; - using System.Text; - - static partial class MoreEnumerable - { - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// Type of element in the source sequence - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// Type of element in the source sequence - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - if (source == null) throw new ArgumentNullException("source"); - return ToDelimitedStringImpl(source, delimiter, (sb, e) => sb.Append(e)); - } - - static string ToDelimitedStringImpl(IEnumerable source, string delimiter, Func append) - { - Debug.Assert(source != null); - Debug.Assert(append != null); - - delimiter = delimiter ?? CultureInfo.CurrentCulture.TextInfo.ListSeparator; - var sb = new StringBuilder(); - var i = 0; - - foreach (var value in source) - { - if (i++ > 0) sb.Append(delimiter); - append(sb, value); - } - - return sb.ToString(); - } - } -} +#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; + using System.Diagnostics; + using System.Globalization; + using System.Text; + + static partial class MoreEnumerable + { + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// Type of element in the source sequence + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// Type of element in the source sequence + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + if (source == null) throw new ArgumentNullException("source"); + return ToDelimitedStringImpl(source, delimiter, (sb, e) => sb.Append(e)); + } + + static string ToDelimitedStringImpl(IEnumerable source, string delimiter, Func append) + { + Debug.Assert(source != null); + Debug.Assert(append != null); + + delimiter = delimiter ?? CultureInfo.CurrentCulture.TextInfo.ListSeparator; + var sb = new StringBuilder(); + var i = 0; + + foreach (var value in source) + { + if (i++ > 0) sb.Append(delimiter); + append(sb, value); + } + + return sb.ToString(); + } + } +} diff --git a/MoreLinq/ToDelimitedString.g.cs b/MoreLinq/ToDelimitedString.g.cs index c115fafe3..103516a6d 100644 --- a/MoreLinq/ToDelimitedString.g.cs +++ b/MoreLinq/ToDelimitedString.g.cs @@ -1,547 +1,547 @@ -#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; - using System.Text; - - partial class MoreEnumerable - { - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func String = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.String); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Boolean = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Boolean); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func SByte = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.SByte); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Byte = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Byte); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Char = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Char); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Int16 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int16); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Int32 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int32); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Int64 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int64); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Single = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Single); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Double = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Double); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func Decimal = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Decimal); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func UInt16 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt16); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func UInt32 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt32); - } - - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func UInt64 = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt64); - } - - - static partial class StringBuilderAppenders {} - } -} +#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; + using System.Text; + + partial class MoreEnumerable + { + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func String = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.String); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Boolean = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Boolean); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func SByte = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.SByte); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Byte = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Byte); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Char = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Char); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Int16 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int16); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Int32 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int32); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Int64 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Int64); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Single = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Single); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Double = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Double); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func Decimal = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.Decimal); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func UInt16 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt16); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func UInt32 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt32); + } + + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func UInt64 = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.UInt64); + } + + + static partial class StringBuilderAppenders {} + } +} diff --git a/MoreLinq/ToDelimitedString.g.tt b/MoreLinq/ToDelimitedString.g.tt index 5636c742b..f671206a5 100644 --- a/MoreLinq/ToDelimitedString.g.tt +++ b/MoreLinq/ToDelimitedString.g.tt @@ -1,89 +1,89 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ output extension=".cs" #> -<#@ import namespace="System.CodeDom" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Reflection" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="Microsoft.CSharp" #> -#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; - using System.Text; - - partial class MoreEnumerable - { -<# var cscp = new CSharpCodeProvider(); - var types = - from method in typeof(StringBuilder).GetMethods(BindingFlags.Public | BindingFlags.Instance) - where "Append" == method.Name - select method.GetParameters() into parameters - where parameters.Length == 1 - select parameters.First().ParameterType into type - where type.IsValueType || type == typeof(string) - select new - { - Type = type, - Name = cscp.GetTypeOutput(new CodeTypeReference(type)), - }; - foreach (var type in types) { #> - /// - /// Creates a delimited string from a sequence of values. The - /// delimiter used depends on the current culture of the executing thread. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - - public static string ToDelimitedString(this IEnumerable<<#= type.Name #>> source) - { - return ToDelimitedString(source, null); - } - - static partial class StringBuilderAppenders - { - public static readonly Func, StringBuilder> <#= type.Type.Name #> = (sb, e) => sb.Append(e); - } - - /// - /// Creates a delimited string from a sequence of values and - /// a given delimiter. - /// - /// - /// This operator uses immediate execution and effectively buffers the sequence. - /// - /// The sequence of items to delimit. Each is converted to a string using the - /// simple ToString() conversion. - /// The delimiter to inject between elements. May be null, in which case - /// the executing thread's current culture's list separator is used. - - public static string ToDelimitedString(this IEnumerable<<#= type.Name #>> source, string delimiter) - { - return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.<#= type.Type.Name #>); - } - -<# } #> - - static partial class StringBuilderAppenders {} - } -} +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ import namespace="System.CodeDom" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Reflection" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="Microsoft.CSharp" #> +#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; + using System.Text; + + partial class MoreEnumerable + { +<# var cscp = new CSharpCodeProvider(); + var types = + from method in typeof(StringBuilder).GetMethods(BindingFlags.Public | BindingFlags.Instance) + where "Append" == method.Name + select method.GetParameters() into parameters + where parameters.Length == 1 + select parameters.First().ParameterType into type + where type.IsValueType || type == typeof(string) + select new + { + Type = type, + Name = cscp.GetTypeOutput(new CodeTypeReference(type)), + }; + foreach (var type in types) { #> + /// + /// Creates a delimited string from a sequence of values. The + /// delimiter used depends on the current culture of the executing thread. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + + public static string ToDelimitedString(this IEnumerable<<#= type.Name #>> source) + { + return ToDelimitedString(source, null); + } + + static partial class StringBuilderAppenders + { + public static readonly Func, StringBuilder> <#= type.Type.Name #> = (sb, e) => sb.Append(e); + } + + /// + /// Creates a delimited string from a sequence of values and + /// a given delimiter. + /// + /// + /// This operator uses immediate execution and effectively buffers the sequence. + /// + /// The sequence of items to delimit. Each is converted to a string using the + /// simple ToString() conversion. + /// The delimiter to inject between elements. May be null, in which case + /// the executing thread's current culture's list separator is used. + + public static string ToDelimitedString(this IEnumerable<<#= type.Name #>> source, string delimiter) + { + return ToDelimitedStringImpl(source, delimiter, StringBuilderAppenders.<#= type.Type.Name #>); + } + +<# } #> + + static partial class StringBuilderAppenders {} + } +} diff --git a/MoreLinq/ToHashSet.cs b/MoreLinq/ToHashSet.cs index 32a8fcb54..ecc871f04 100644 --- a/MoreLinq/ToHashSet.cs +++ b/MoreLinq/ToHashSet.cs @@ -1,60 +1,60 @@ -#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; - - // TODO: Tests! (The code is simple enough I trust it not to fail, mind you...) - static partial class MoreEnumerable - { - /// - /// Returns a of the source items using the default equality - /// comparer for the type. - /// - /// - /// This evaluates the input sequence completely. - /// - /// Source sequence - /// A hash set of the items in the sequence, using the default equality comparer. - /// is null - - public static HashSet ToHashSet(this IEnumerable source) - { - return source.ToHashSet(null); - } - - /// - /// Returns a of the source items using the specified equality - /// comparer for the type. - /// - /// - /// This evaluates the input sequence completely. - /// - /// Source sequence - /// Equality comparer to use; a value of null will cause the type's default equality comparer to be used - /// A hash set of the items in the sequence, using the default equality comparer. - /// is null - - public static HashSet ToHashSet(this IEnumerable source, IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - return new HashSet(source, comparer); - } - } -} +#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; + + // TODO: Tests! (The code is simple enough I trust it not to fail, mind you...) + static partial class MoreEnumerable + { + /// + /// Returns a of the source items using the default equality + /// comparer for the type. + /// + /// + /// This evaluates the input sequence completely. + /// + /// Source sequence + /// A hash set of the items in the sequence, using the default equality comparer. + /// is null + + public static HashSet ToHashSet(this IEnumerable source) + { + return source.ToHashSet(null); + } + + /// + /// Returns a of the source items using the specified equality + /// comparer for the type. + /// + /// + /// This evaluates the input sequence completely. + /// + /// Source sequence + /// Equality comparer to use; a value of null will cause the type's default equality comparer to be used + /// A hash set of the items in the sequence, using the default equality comparer. + /// is null + + public static HashSet ToHashSet(this IEnumerable source, IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + return new HashSet(source, comparer); + } + } +} diff --git a/MoreLinq/Trace.cs b/MoreLinq/Trace.cs index d34c49d77..305c27fd7 100644 --- a/MoreLinq/Trace.cs +++ b/MoreLinq/Trace.cs @@ -1,106 +1,106 @@ -#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; - using System.Diagnostics; - - static partial class MoreEnumerable - { - /// - /// Traces the elements of a source sequence for diagnostics. - /// - /// Type of element in the source sequence - /// Source sequence whose elements to trace. - /// - /// Return the source sequence unmodified. - /// - /// - /// This a pass-through operator that uses deferred execution and - /// streams the results. - /// - - public static IEnumerable Trace(this IEnumerable source) - { - return Trace(source, (string) null); - } - - /// - /// Traces the elements of a source sequence for diagnostics using - /// custom formatting. - /// - /// Type of element in the source sequence - /// Source sequence whose elements to trace. - /// - /// String to use to format the trace message. If null then the - /// element value becomes the traced message. - /// - /// - /// Return the source sequence unmodified. - /// - /// - /// This a pass-through operator that uses deferred execution and - /// streams the results. - /// - - public static IEnumerable Trace(this IEnumerable source, string format) - { - if (source == null) throw new ArgumentNullException("source"); - - return TraceImpl(source, - string.IsNullOrEmpty(format) - ? (Func) (x => x == null ? string.Empty : x.ToString()) - : (x => string.Format(format, x))); - } - - /// - /// Traces the elements of a source sequence for diagnostics using - /// a custom formatter. - /// - /// Type of element in the source sequence - /// Source sequence whose elements to trace. - /// Function used to format each source element into a string. - /// - /// Return the source sequence unmodified. - /// - /// - /// This a pass-through operator that uses deferred execution and - /// streams the results. - /// - - public static IEnumerable Trace(this IEnumerable source, Func formatter) - { - if (source == null) throw new ArgumentNullException("source"); - if (formatter == null) throw new ArgumentNullException("formatter"); - return TraceImpl(source, formatter); - } - - private static IEnumerable TraceImpl(IEnumerable source, Func formatter) - { - Debug.Assert(source != null); - Debug.Assert(formatter != null); - - return source -#if !NO_TRACING - .Pipe(x => System.Diagnostics.Trace.WriteLine(formatter(x))) -#endif - ; - } - } -} +#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; + using System.Diagnostics; + + static partial class MoreEnumerable + { + /// + /// Traces the elements of a source sequence for diagnostics. + /// + /// Type of element in the source sequence + /// Source sequence whose elements to trace. + /// + /// Return the source sequence unmodified. + /// + /// + /// This a pass-through operator that uses deferred execution and + /// streams the results. + /// + + public static IEnumerable Trace(this IEnumerable source) + { + return Trace(source, (string) null); + } + + /// + /// Traces the elements of a source sequence for diagnostics using + /// custom formatting. + /// + /// Type of element in the source sequence + /// Source sequence whose elements to trace. + /// + /// String to use to format the trace message. If null then the + /// element value becomes the traced message. + /// + /// + /// Return the source sequence unmodified. + /// + /// + /// This a pass-through operator that uses deferred execution and + /// streams the results. + /// + + public static IEnumerable Trace(this IEnumerable source, string format) + { + if (source == null) throw new ArgumentNullException("source"); + + return TraceImpl(source, + string.IsNullOrEmpty(format) + ? (Func) (x => x == null ? string.Empty : x.ToString()) + : (x => string.Format(format, x))); + } + + /// + /// Traces the elements of a source sequence for diagnostics using + /// a custom formatter. + /// + /// Type of element in the source sequence + /// Source sequence whose elements to trace. + /// Function used to format each source element into a string. + /// + /// Return the source sequence unmodified. + /// + /// + /// This a pass-through operator that uses deferred execution and + /// streams the results. + /// + + public static IEnumerable Trace(this IEnumerable source, Func formatter) + { + if (source == null) throw new ArgumentNullException("source"); + if (formatter == null) throw new ArgumentNullException("formatter"); + return TraceImpl(source, formatter); + } + + private static IEnumerable TraceImpl(IEnumerable source, Func formatter) + { + Debug.Assert(source != null); + Debug.Assert(formatter != null); + + return source +#if !NO_TRACING + .Pipe(x => System.Diagnostics.Trace.WriteLine(formatter(x))) +#endif + ; + } + } +} diff --git a/MoreLinq/Zip.cs b/MoreLinq/Zip.cs index c4755c70b..aa2a130d8 100644 --- a/MoreLinq/Zip.cs +++ b/MoreLinq/Zip.cs @@ -1,75 +1,75 @@ -#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 projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// - /// If the two input sequences are of different lengths, the result sequence - /// is terminated as soon as the shortest input sequence is exhausted. - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 1, 2, 3 }; - /// string[] letters = { "A", "B", "C", "D" }; - /// var zipped = numbers.Zip(letters, (n, l) => n + l); - /// - /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", in turn. - /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in result sequence - /// First sequence - /// Second sequence - /// Function to apply to each pair of elements - - public static IEnumerable Zip(this IEnumerable first, - IEnumerable second, Func resultSelector) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return ZipImpl(first, second, resultSelector); - } - - static IEnumerable ZipImpl( - IEnumerable first, - IEnumerable second, - Func resultSelector) - { - using (var e1 = first.GetEnumerator()) - using (var e2 = second.GetEnumerator()) - { - while (e1.MoveNext()) - { - if (e2.MoveNext()) - yield return resultSelector(e1.Current, e2.Current); - } - } - } - } -} +#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 projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the two input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted. + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 1, 2, 3 }; + /// string[] letters = { "A", "B", "C", "D" }; + /// var zipped = numbers.Zip(letters, (n, l) => n + l); + /// + /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", in turn. + /// + /// Type of elements in first sequence + /// Type of elements in second sequence + /// Type of elements in result sequence + /// First sequence + /// Second sequence + /// Function to apply to each pair of elements + + public static IEnumerable Zip(this IEnumerable first, + IEnumerable second, Func resultSelector) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return ZipImpl(first, second, resultSelector); + } + + static IEnumerable ZipImpl( + IEnumerable first, + IEnumerable second, + Func resultSelector) + { + using (var e1 = first.GetEnumerator()) + using (var e2 = second.GetEnumerator()) + { + while (e1.MoveNext()) + { + if (e2.MoveNext()) + yield return resultSelector(e1.Current, e2.Current); + } + } + } + } +} diff --git a/MoreLinq/Zip.stub.cs b/MoreLinq/Zip.stub.cs index 2d2048897..a6616c06e 100644 --- a/MoreLinq/Zip.stub.cs +++ b/MoreLinq/Zip.stub.cs @@ -1,4 +1,4 @@ -// An implementation of Zip for sequences is included in Microsoft .NET -// Framework starting with version 4.0 and is identical to Zip in MoreLINQ. -// For more information on Zip, see the following reference on MSDN: -// http://msdn.microsoft.com/en-us/library/dd267698.aspx +// An implementation of Zip for sequences is included in Microsoft .NET +// Framework starting with version 4.0 and is identical to Zip in MoreLINQ. +// For more information on Zip, see the following reference on MSDN: +// http://msdn.microsoft.com/en-us/library/dd267698.aspx diff --git a/MoreLinq/ZipLongest.cs b/MoreLinq/ZipLongest.cs index b532b07a2..bc62da24d 100644 --- a/MoreLinq/ZipLongest.cs +++ b/MoreLinq/ZipLongest.cs @@ -1,90 +1,90 @@ -#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 projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// - /// If the two input sequences are of different lengths then the result - /// sequence will always be as long as the longer of the two input sequences. - /// The default value of the shorter sequence element type is used for padding. - /// This operator uses deferred execution and streams its results. - /// - /// - /// - /// int[] numbers = { 1, 2, 3 }; - /// string[] letters = { "A", "B", "C", "D" }; - /// var zipped = numbers.EquiZip(letters, (n, l) => n + l); - /// - /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", "0D" in turn. - /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in result sequence - /// First sequence - /// Second sequence - /// Function to apply to each pair of elements - - public static IEnumerable ZipLongest(this IEnumerable first, - IEnumerable second, - Func resultSelector) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return ZipLongestImpl(first, second, resultSelector); - } - - static IEnumerable ZipLongestImpl( - IEnumerable first, - IEnumerable second, - Func resultSelector) - { - using (var e1 = first.GetEnumerator()) - using (var e2 = second.GetEnumerator()) - { - while (e1.MoveNext()) - { - if (e2.MoveNext()) - { - yield return resultSelector(e1.Current, e2.Current); - } - else - { - do { yield return resultSelector(e1.Current, default(TSecond)); } - while (e1.MoveNext()); - yield break; - } - } - if (e2.MoveNext()) - { - do { yield return resultSelector(default(TFirst), e2.Current); } - while (e2.MoveNext()); - } - } - } - } -} +#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 projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the two input sequences are of different lengths then the result + /// sequence will always be as long as the longer of the two input sequences. + /// The default value of the shorter sequence element type is used for padding. + /// This operator uses deferred execution and streams its results. + /// + /// + /// + /// int[] numbers = { 1, 2, 3 }; + /// string[] letters = { "A", "B", "C", "D" }; + /// var zipped = numbers.EquiZip(letters, (n, l) => n + l); + /// + /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", "0D" in turn. + /// + /// Type of elements in first sequence + /// Type of elements in second sequence + /// Type of elements in result sequence + /// First sequence + /// Second sequence + /// Function to apply to each pair of elements + + public static IEnumerable ZipLongest(this IEnumerable first, + IEnumerable second, + Func resultSelector) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return ZipLongestImpl(first, second, resultSelector); + } + + static IEnumerable ZipLongestImpl( + IEnumerable first, + IEnumerable second, + Func resultSelector) + { + using (var e1 = first.GetEnumerator()) + using (var e2 = second.GetEnumerator()) + { + while (e1.MoveNext()) + { + if (e2.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current); + } + else + { + do { yield return resultSelector(e1.Current, default(TSecond)); } + while (e1.MoveNext()); + yield break; + } + } + if (e2.MoveNext()) + { + do { yield return resultSelector(default(TFirst), e2.Current); } + while (e2.MoveNext()); + } + } + } + } +} diff --git a/bn.py b/bn.py index 249e0e52e..b1cf36651 100644 --- a/bn.py +++ b/bn.py @@ -1,6 +1,6 @@ -import sys -from time import gmtime -year, mon, mday, hour, min, sec, wday, yday, isdst = gmtime() -bld = ((year - 2000) * 12 + mon - 1) * 100 + mday -rev = hour * 100 + min -print 'Your build and revision number for today is %d.%d.' % (bld, rev) +import sys +from time import gmtime +year, mon, mday, hour, min, sec, wday, yday, isdst = gmtime() +bld = ((year - 2000) * 12 + mon - 1) * 100 + mday +rev = hour * 100 + min +print 'Your build and revision number for today is %d.%d.' % (bld, rev) diff --git a/build.cmd b/build.cmd index af4558cb0..452d83522 100644 --- a/build.cmd +++ b/build.cmd @@ -1,19 +1,19 @@ -@echo off -setlocal -cd "%~dp0" -set MSBUILDEXE=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe -if not exist "%MSBUILDEXE%" ( - echo The .NET Framework 4.0 does not appear to be installed on this - echo machine, which is required to build the solution. - exit /b 1 -) -if "%1"=="docs" call :docs %2 %3 %4 %5 %6 %7 %8 %9 & goto :EOF - -:base -for %%i in (debug release) do "%MSBUILDEXE%" "MoreLinq.sln" /v:m /p:Configuration=%%i %* -goto :EOF - -:docs -call :base -"%MSBUILDEXE%" MoreLinq.shfbproj %* -goto :EOF +@echo off +setlocal +cd "%~dp0" +set MSBUILDEXE=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe +if not exist "%MSBUILDEXE%" ( + echo The .NET Framework 4.0 does not appear to be installed on this + echo machine, which is required to build the solution. + exit /b 1 +) +if "%1"=="docs" call :docs %2 %3 %4 %5 %6 %7 %8 %9 & goto :EOF + +:base +for %%i in (debug release) do "%MSBUILDEXE%" "MoreLinq.sln" /v:m /p:Configuration=%%i %* +goto :EOF + +:docs +call :base +"%MSBUILDEXE%" MoreLinq.shfbproj %* +goto :EOF diff --git a/builddocs.cmd b/builddocs.cmd index 845e400d1..a46f09c1e 100644 --- a/builddocs.cmd +++ b/builddocs.cmd @@ -1 +1 @@ -@"%~dp0build" docs +@"%~dp0build" docs diff --git a/buildw.cmd b/buildw.cmd index 4d5f1bed1..6bb26f728 100644 --- a/buildw.cmd +++ b/buildw.cmd @@ -1,3 +1,3 @@ -@echo off -call "%~dp0build" %* -pause +@echo off +call "%~dp0build" %* +pause diff --git a/docs/api/Index.html b/docs/api/Index.html index 81a69926d..7273f11ee 100644 --- a/docs/api/Index.html +++ b/docs/api/Index.html @@ -1,468 +1,468 @@ - - - - -MoreLinq - Table of Content - - - - - - -
- -
- - - - - - - - - - - -
-
-MoreLinq Namespace - -
- -
- -
- -
- - - -
- - - - + + + + +MoreLinq - Table of Content + + + + + + +
+ +
+ + + + + + + + + + + +
+
+MoreLinq Namespace + +
+ +
+ +
+ +
+ + + +
+ + + + diff --git a/docs/api/TOC.css b/docs/api/TOC.css index 560563c26..e718b9d05 100644 --- a/docs/api/TOC.css +++ b/docs/api/TOC.css @@ -1,163 +1,163 @@ -/* File : TOC.css -// Author : Eric Woodruff (Eric@EWoodruff.us) -// Updated : 09/07/2007 -// -// Stylesheet for the table of content -*/ - -* -{ - margin: 0px 0px 0px 0px; - padding: 0px 0px 0px 0px; -} - -body -{ - font-family: verdana, arial, sans-serif; - font-size: 8.5pt; - background-color: #6699CC; - color: White; - overflow: hidden; -} - -input -{ - font-size: 8.5pt; -} - -img -{ - border: 0; - margin-left: 5px; - margin-right: 2px; -} - -img.TreeNodeImg -{ - cursor: pointer; -} - -img.TOCLink -{ - cursor: pointer; - margin-left: 0; - margin-right: 0; -} - -a.SelectedNode, a.UnselectedNode -{ - color: black; - text-decoration: none; - padding: 1px 3px 1px 3px; - white-space: nowrap; -} - -a.SelectedNode -{ - background-color: #ffffff; - border: solid 1px #999999; - padding: 0px 2px 0px 2px; -} - -a.UnselectedNode:hover, a.SelectedNode:hover -{ - background-color: #cccccc; - border: solid 1px #999999; - padding: 0px 2px 0px 2px; -} - -.Visible -{ - display: block; - margin-left: 2em; -} - -.Hidden -{ - display: none; -} - -.Tree -{ - background-color: #f0f0f0; - color: Black; - width: 300px; - overflow: auto; -} - -.TreeNode, .TreeItem -{ - white-space: nowrap; - margin: 2px 2px 2px 2px; -} - -.TOCDiv -{ - position: relative; - float: left; - width: 300px; - height: 100%; -} - -.TOCSizer -{ - clear: none; - float: left; - width: 10px; - height: 100%; - background-color: #6699CC; - background-image: url("Splitter.gif"); - background-position:center center; - background-repeat:no-repeat; - position: relative; - cursor: w-resize; -} - -.TopicContent -{ - position: relative; - float: right; - background-color: white; - height: 100%; -} - -.SearchOpts -{ - padding: 5px 5px 0px 5px; - background-color: lightgrey; - color: black; - width: 300px; -} - -.NavOpts -{ - padding: 5px 5px 0px 5px; - background-color: lightgrey; - color: black; - width: 300px; -} - -.IndexOpts -{ - padding: 5px 5px 0px 5px; - background-color: lightgrey; - color: black; - width: 300px; -} - -.IndexItem -{ - white-space: nowrap; - margin: 2px 2px 2px 2px; -} - -.IndexSubItem -{ - white-space: nowrap; - margin: 2px 2px 2px 12px; -} - -.PaddedText -{ - margin: 10px 10px 10px 10px; -} +/* File : TOC.css +// Author : Eric Woodruff (Eric@EWoodruff.us) +// Updated : 09/07/2007 +// +// Stylesheet for the table of content +*/ + +* +{ + margin: 0px 0px 0px 0px; + padding: 0px 0px 0px 0px; +} + +body +{ + font-family: verdana, arial, sans-serif; + font-size: 8.5pt; + background-color: #6699CC; + color: White; + overflow: hidden; +} + +input +{ + font-size: 8.5pt; +} + +img +{ + border: 0; + margin-left: 5px; + margin-right: 2px; +} + +img.TreeNodeImg +{ + cursor: pointer; +} + +img.TOCLink +{ + cursor: pointer; + margin-left: 0; + margin-right: 0; +} + +a.SelectedNode, a.UnselectedNode +{ + color: black; + text-decoration: none; + padding: 1px 3px 1px 3px; + white-space: nowrap; +} + +a.SelectedNode +{ + background-color: #ffffff; + border: solid 1px #999999; + padding: 0px 2px 0px 2px; +} + +a.UnselectedNode:hover, a.SelectedNode:hover +{ + background-color: #cccccc; + border: solid 1px #999999; + padding: 0px 2px 0px 2px; +} + +.Visible +{ + display: block; + margin-left: 2em; +} + +.Hidden +{ + display: none; +} + +.Tree +{ + background-color: #f0f0f0; + color: Black; + width: 300px; + overflow: auto; +} + +.TreeNode, .TreeItem +{ + white-space: nowrap; + margin: 2px 2px 2px 2px; +} + +.TOCDiv +{ + position: relative; + float: left; + width: 300px; + height: 100%; +} + +.TOCSizer +{ + clear: none; + float: left; + width: 10px; + height: 100%; + background-color: #6699CC; + background-image: url("Splitter.gif"); + background-position:center center; + background-repeat:no-repeat; + position: relative; + cursor: w-resize; +} + +.TopicContent +{ + position: relative; + float: right; + background-color: white; + height: 100%; +} + +.SearchOpts +{ + padding: 5px 5px 0px 5px; + background-color: lightgrey; + color: black; + width: 300px; +} + +.NavOpts +{ + padding: 5px 5px 0px 5px; + background-color: lightgrey; + color: black; + width: 300px; +} + +.IndexOpts +{ + padding: 5px 5px 0px 5px; + background-color: lightgrey; + color: black; + width: 300px; +} + +.IndexItem +{ + white-space: nowrap; + margin: 2px 2px 2px 2px; +} + +.IndexSubItem +{ + white-space: nowrap; + margin: 2px 2px 2px 12px; +} + +.PaddedText +{ + margin: 10px 10px 10px 10px; +} diff --git a/docs/api/TOC.js b/docs/api/TOC.js index cb9105aaa..4243548dd 100644 --- a/docs/api/TOC.js +++ b/docs/api/TOC.js @@ -1,757 +1,757 @@ -//============================================================================= -// System : Sandcastle Help File Builder -// File : TOC.js -// Author : Eric Woodruff (Eric@EWoodruff.us) -// Updated : 07/25/2012 -// Note : Copyright 2006-2012, Eric Woodruff, All rights reserved -// Compiler: JavaScript -// -// This file contains the methods necessary to implement a simple tree view -// for the table of content with a resizable splitter and Ajax support to -// load tree nodes on demand. It also contains the script necessary to do -// full-text searches. -// -// This code is published under the Microsoft Public License (Ms-PL). A copy -// of the license should be distributed with the code. It can also be found -// at the project website: http://SHFB.CodePlex.com. This notice, the -// author's name, and all copyright notices must remain intact in all -// applications, documentation, and source files. -// -// Version Date Who Comments -// ============================================================================ -// 1.3.0.0 09/12/2006 EFW Created the code -// 1.4.0.2 06/15/2007 EFW Reworked to get rid of frame set and to add -// support for Ajax to load tree nodes on demand. -// 1.5.0.0 06/24/2007 EFW Added full-text search capabilities -// 1.6.0.7 04/01/2008 EFW Merged changes from Ferdinand Prantl to add a -// website keyword index. Added support for "topic" -// query string option. -// 1.9.4.0 02/21/2012 EFW Merged code from Thomas Levesque to show direct -// link and support other page types like PHP. -// 1.9.5.0 07/25/2012 EFW Made changes to support IE 10. -//============================================================================= - -// IE and Chrome flags -var isIE = (navigator.userAgent.indexOf("MSIE") >= 0); -var isIE10OrLater = /MSIE 1\d\./.test(navigator.userAgent); -var isChrome = (navigator.userAgent.indexOf("Chrome") >= 0); - -// Page extension -var pageExtension = ".aspx"; - -// Minimum width of the TOC div -var minWidth = 100; - -// Elements and sizing info -var divTOC, divSizer, topicContent, divNavOpts, divSearchOpts, divSearchResults, divIndexOpts, divIndexResults, - divTree, docBody, maxWidth, offset, txtSearchText, chkSortByTitle; - -// Last node selected -var lastNode, lastSearchNode, lastIndexNode; - -// Last page with keyword index -var currentIndexPage = 0; - -//============================================================================ - -// Initialize the tree view and resize the content. Pass it the page extension to use (i.e. ".aspx") -// for loading TOC element, index keywords, searching, etc. -function Initialize(extension) -{ - docBody = document.getElementsByTagName("body")[0]; - divTOC = document.getElementById("TOCDiv"); - divSizer = document.getElementById("TOCSizer"); - topicContent = document.getElementById("TopicContent"); - divNavOpts = document.getElementById("divNavOpts"); - divSearchOpts = document.getElementById("divSearchOpts"); - divSearchResults = document.getElementById("divSearchResults"); - divIndexOpts = document.getElementById("divIndexOpts"); - divIndexResults = document.getElementById("divIndexResults"); - divTree = document.getElementById("divTree"); - txtSearchText = document.getElementById("txtSearchText"); - chkSortByTitle = document.getElementById("chkSortByTitle"); - - // Set the page extension if specified - if(typeof(extension) != "undefined" && extension != "") - pageExtension = extension; - - // The sizes are bit off in FireFox - if(!isIE) - divNavOpts.style.width = divSearchOpts.style.width = divIndexOpts.style.width = 292; - - ResizeTree(); - SyncTOC(); - - topicContent.onload = SyncTOC; - - // Use an alternate default page if a topic is specified in - // the query string. - var queryString = document.location.search; - - if(queryString != "") - { - var idx, options = queryString.split(/[\?\=\&]/); - - for(idx = 0; idx < options.length; idx++) - if(options[idx] == "topic" && idx + 1 < options.length) - { - topicContent.src = options[idx + 1]; - break; - } - } -} - -//============================================================================ -// Navigation and expand/collaps code - -// Synchronize the table of content with the selected page if possible -function SyncTOC() -{ - var idx, anchor, base, href, url, anchors, treeNode, saveNode; - - base = window.location.href; - base = base.substr(0, base.lastIndexOf("/") + 1); - - if(base.substr(0, 5) == "file:" && base.substr(0, 8) != "file:///") - base = base.replace("file://", "file:///"); - - url = GetCurrentUrl(); - - if(url == "") - return false; - - if(url.substr(0, 5) == "file:" && url.substr(0, 8) != "file:///") - url = url.replace("file://", "file:///"); - - while(true) - { - anchors = divTree.getElementsByTagName("A"); - anchor = null; - - for(idx = 0; idx < anchors.length; idx++) - { - href = anchors[idx].href; - - if(href.substring(0, 7) != 'http://' && href.substring(0, 8) != 'https://' && - href.substring(0, 7) != 'file://') - href = base + href; - - if(href == url) - { - anchor = anchors[idx]; - break; - } - } - - if(anchor == null) - { - // If it contains a "#", strip anything after that and try again - if(url.indexOf("#") != -1) - { - url = url.substr(0, url.indexOf("#")); - continue; - } - - return; - } - - break; - } - - // If found, select it and find the parent tree node - SelectNode(anchor); - saveNode = anchor; - lastNode = null; - - while(anchor != null) - { - if(anchor.className == "TreeNode") - { - treeNode = anchor; - break; - } - - anchor = anchor.parentNode; - } - - // Expand it and all of its parents - while(anchor != null) - { - Expand(anchor); - - anchor = anchor.parentNode; - - while(anchor != null) - { - if(anchor.className == "TreeNode") - break; - - anchor = anchor.parentNode; - } - } - - lastNode = saveNode; - - // Scroll the node into view - var windowTop = lastNode.offsetTop - divTree.offsetTop - divTree.scrollTop; - var windowBottom = divTree.clientHeight - windowTop - lastNode.offsetHeight; - - if(windowTop < 0) - divTree.scrollTop += windowTop - 30; - else - if(windowBottom < 0) - divTree.scrollTop -= windowBottom - 30; -} - -// Get the currently loaded URL from the IFRAME -function GetCurrentUrl() -{ - var base, url = ""; - - try - { - url = window.frames["TopicContent"].document.URL.replace(/\\/g, "/"); - } - catch(e) - { - // If this happens the user probably navigated to another frameset that didn't make itself the topmost - // frameset and we don't have control of the other frame anymore. In that case, just reload our index - // page. - base = window.location.href; - base = base.substr(0, base.lastIndexOf("/") + 1); - - // Chrome is too secure and won't let you access frame URLs when running from the file system unless - // you run Chrome with the "--disable-web-security" command line option. - if(isChrome && base.substr(0, 5) == "file:") - { - alert("Chrome security prevents access to file-based frame URLs. As such, the TOC will not work " + - "with Index.html. Either run this website on a web server, run Chrome with the " + - "'--disable-web-security' command line option, or use FireFox or Internet Explorer."); - - return ""; - } - - if(base.substr(0, 5) == "file:" && base.substr(0, 8) != "file:///") - base = base.replace("file://", "file:///"); - - if(base.substr(0, 5) == "file:") - top.location.href = base + "Index.html"; - else - top.location.href = base + "index" + pageExtension; // Use lowercase on name for case-sensitive servers - } - - return url; -} - -// Expand or collapse all nodes -function ExpandOrCollapseAll(expandNodes) -{ - var divIdx, childIdx, img, divs = document.getElementsByTagName("DIV"); - var childNodes, child, div, link, img; - - for(divIdx = 0; divIdx < divs.length; divIdx++) - if(divs[divIdx].className == "Hidden" || divs[divIdx].className == "Visible") - { - childNodes = divs[divIdx].parentNode.childNodes; - - for(childIdx = 0; childIdx < childNodes.length; childIdx++) - { - child = childNodes[childIdx]; - - if(child.className == "TreeNodeImg") - img = child; - - if(child.className == "Hidden" || child.className == "Visible") - { - div = child; - break; - } - } - - if(div.className == "Visible" && !expandNodes) - { - div.className = "Hidden"; - img.src = "Collapsed.gif"; - } - else - if(div.className == "Hidden" && expandNodes) - { - div.className = "Visible"; - img.src = "Expanded.gif"; - - if(div.innerHTML == "") - FillNode(div, true) - } - } -} - -// Toggle the state of the specified node -function Toggle(node) -{ - var i, childNodes, child, div, link; - - childNodes = node.parentNode.childNodes; - - for(i = 0; i < childNodes.length; i++) - { - child = childNodes[i]; - - if(child.className == "Hidden" || child.className == "Visible") - { - div = child; - break; - } - } - - if(div.className == "Visible") - { - div.className = "Hidden"; - node.src = "Collapsed.gif"; - } - else - { - div.className = "Visible"; - node.src = "Expanded.gif"; - - if(div.innerHTML == "") - FillNode(div, false) - } -} - -// Expand the selected node -function Expand(node) -{ - var i, childNodes, child, div, img; - - // If not valid, don't bother - if(GetCurrentUrl() == "") - return false; - - if(node.tagName == "A") - childNodes = node.parentNode.childNodes; - else - childNodes = node.childNodes; - - for(i = 0; i < childNodes.length; i++) - { - child = childNodes[i]; - - if(child.className == "TreeNodeImg") - img = child; - - if(child.className == "Hidden" || child.className == "Visible") - { - div = child; - break; - } - } - - if(lastNode != null) - lastNode.className = "UnselectedNode"; - - div.className = "Visible"; - img.src = "Expanded.gif"; - - if(node.tagName == "A") - { - node.className = "SelectedNode"; - lastNode = node; - } - - if(div.innerHTML == "") - FillNode(div, false) - - return true; -} - -// Set the style of the specified node to "selected" -function SelectNode(node) -{ - // If not valid, don't bother - if(GetCurrentUrl() == "") - return false; - - if(lastNode != null) - lastNode.className = "UnselectedNode"; - - node.className = "SelectedNode"; - lastNode = node; - - return true; -} - -//============================================================================ -// Ajax-related code used to fill the tree nodes on demand - -function GetXmlHttpRequest() -{ - var xmlHttp = null; - - // If IE7, Mozilla, Safari, etc., use the native object. Otherwise, use the ActiveX control for IE5.x and IE6. - if(window.XMLHttpRequest) - xmlHttp = new XMLHttpRequest(); - else - if(window.ActiveXObject) - xmlHttp = new ActiveXObject("MSXML2.XMLHTTP.3.0"); - - return xmlHttp; -} - -// Perform an AJAX-style request for the contents of a node and put the contents into the empty div -function FillNode(div, expandChildren) -{ - var xmlHttp = GetXmlHttpRequest(), now = new Date(); - - if(xmlHttp == null) - { - div.innerHTML = "XML HTTP request not supported!"; - return; - } - - div.innerHTML = "Loading..."; - - // Add a unique hash to ensure it doesn't use cached results - xmlHttp.open("GET", "FillNode" + pageExtension + "?Id=" + div.id + "&hash=" + now.getTime(), true); - - xmlHttp.onreadystatechange = function() - { - if(xmlHttp.readyState == 4) - { - div.innerHTML = xmlHttp.responseText; - - if(expandChildren) - ExpandOrCollapseAll(true); - } - } - - xmlHttp.send(null) -} - -//============================================================================ -// Resizing code - -// Resize the tree div so that it fills the document body -function ResizeTree() -{ - var y, newHeight; - - if(self.innerHeight) // All but IE - y = self.innerHeight; - else // IE - Strict - if(document.documentElement && document.documentElement.clientHeight) - y = document.documentElement.clientHeight; - else // Everything else - if(document.body) - y = document.body.clientHeight; - - newHeight = y - parseInt(divNavOpts.style.height, 10) - 6; - - if(newHeight < 50) - newHeight = 50; - - divTree.style.height = newHeight; - - newHeight = y - parseInt(divSearchOpts.style.height, 10) - 6; - - if(newHeight < 100) - newHeight = 100; - - divSearchResults.style.height = newHeight; - - newHeight = y - parseInt(divIndexOpts.style.height, 10) - 6; - - if(newHeight < 25) - newHeight = 25; - - divIndexResults.style.height = newHeight; - - // Resize the content div - ResizeContent(); -} - -// Resize the content div -function ResizeContent() -{ - // IE 10 sizes the frame like FireFox and Chrome - if(isIE && !isIE10OrLater) - maxWidth = docBody.clientWidth - 1; - else - maxWidth = docBody.clientWidth - 4; - - topicContent.style.width = maxWidth - (divSizer.offsetLeft + divSizer.offsetWidth); - maxWidth -= minWidth; -} - -// This is called to prepare for dragging the sizer div -function OnMouseDown(event) -{ - var x; - - // Make sure the splitter is at the top of the z-index - divSizer.style.zIndex = 5000; - - // The content is in an IFRAME which steals mouse events so hide it while resizing - topicContent.style.display = "none"; - - if(isIE) - x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft; - else - x = event.clientX + window.scrollX; - - // Save starting offset - offset = parseInt(divSizer.style.left, 10); - - if(isNaN(offset)) - offset = 0; - - offset -= x; - - if(isIE) - { - document.attachEvent("onmousemove", OnMouseMove); - document.attachEvent("onmouseup", OnMouseUp); - window.event.cancelBubble = true; - window.event.returnValue = false; - } - else - { - document.addEventListener("mousemove", OnMouseMove, true); - document.addEventListener("mouseup", OnMouseUp, true); - event.preventDefault(); - } -} - -// Resize the TOC and content divs as the sizer is dragged -function OnMouseMove(event) -{ - var x, pos; - - // Get cursor position with respect to the page - if(isIE) - x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft; - else - x = event.clientX + window.scrollX; - - left = offset + x; - - // Adjusts the width of the TOC divs - pos = (event.clientX > maxWidth) ? maxWidth : (event.clientX < minWidth) ? minWidth : event.clientX; - - divTOC.style.width = divSearchResults.style.width = divIndexResults.style.width = divTree.style.width = pos; - - if(!isIE) - pos -= 8; - - divNavOpts.style.width = divSearchOpts.style.width = divIndexOpts.style.width = pos; - - // Resize the content div to fit in the remaining space - ResizeContent(); -} - -// Finish the drag operation when the mouse button is released -function OnMouseUp(event) -{ - if(isIE) - { - document.detachEvent("onmousemove", OnMouseMove); - document.detachEvent("onmouseup", OnMouseUp); - } - else - { - document.removeEventListener("mousemove", OnMouseMove, true); - document.removeEventListener("mouseup", OnMouseUp, true); - } - - // Show the content div again - topicContent.style.display = "inline"; -} - -//============================================================================ -// Search code - -function ShowHideSearch(show) -{ - if(show) - { - divNavOpts.style.display = divTree.style.display = "none"; - divSearchOpts.style.display = divSearchResults.style.display = ""; - } - else - { - divSearchOpts.style.display = divSearchResults.style.display = "none"; - divNavOpts.style.display = divTree.style.display = ""; - } -} - -// When enter is hit in the search text box, do the search -function OnSearchTextKeyPress(evt) -{ - if(evt.keyCode == 13) - { - PerformSearch(); - return false; - } - - return true; -} - -// Perform a keyword search -function PerformSearch() -{ - var xmlHttp = GetXmlHttpRequest(), now = new Date(); - - if(xmlHttp == null) - { - divSearchResults.innerHTML = "XML HTTP request not supported!"; - return; - } - - divSearchResults.innerHTML = "Searching..."; - - // Add a unique hash to ensure it doesn't use cached results - xmlHttp.open("GET", "SearchHelp" + pageExtension + "?Keywords=" + txtSearchText.value + - "&SortByTitle=" + (chkSortByTitle.checked ? "true" : "false") + - "&hash=" + now.getTime(), true); - - xmlHttp.onreadystatechange = function() - { - if(xmlHttp.readyState == 4) - { - divSearchResults.innerHTML = xmlHttp.responseText; - - lastSearchNode = divSearchResults.childNodes[0].childNodes[1]; - - while(lastSearchNode != null && lastSearchNode.tagName != "A") - lastSearchNode = lastSearchNode.nextSibling; - - if(lastSearchNode != null) - { - SelectSearchNode(lastSearchNode); - topicContent.src = lastSearchNode.href; - } - } - } - - xmlHttp.send(null) -} - -// Set the style of the specified search result node to "selected" -function SelectSearchNode(node) -{ - if(lastSearchNode != null) - lastSearchNode.className = "UnselectedNode"; - - node.className = "SelectedNode"; - lastSearchNode = node; - - return true; -} - -//============================================================================ -// KeyWordIndex code - -function ShowHideIndex(show) -{ - if(show) - { - PopulateIndex(currentIndexPage); - - divNavOpts.style.display = divTree.style.display = "none"; - divIndexOpts.style.display = divIndexResults.style.display = ""; - } - else - { - divIndexOpts.style.display = divIndexResults.style.display = "none"; - divNavOpts.style.display = divTree.style.display = ""; - } -} - -// Populate keyword index -function PopulateIndex(startIndex) -{ - var xmlHttp = GetXmlHttpRequest(), now = new Date(); - var firstNode; - - if(xmlHttp == null) - { - divIndexResults.innerHTML = "XML HTTP request not supported!"; - return; - } - - divIndexResults.innerHTML = "Loading keyword index..."; - - // Add a unique hash to ensure it doesn't use cached results - xmlHttp.open("GET", "LoadIndexKeywords" + pageExtension + "?StartIndex=" + startIndex + - "&hash=" + now.getTime(), true); - - xmlHttp.onreadystatechange = function() - { - if(xmlHttp.readyState == 4) - { - divIndexResults.innerHTML = xmlHttp.responseText; - - if(startIndex > 0) - { - firstNode = divIndexResults.childNodes[1]; - - if(firstNode != null && !firstNode.innerHTML) - firstNode = divIndexResults.childNodes[2]; - } - else - firstNode = divIndexResults.childNodes[0]; - - if(firstNode != null) - lastIndexNode = firstNode.childNodes[0]; - - while(lastIndexNode != null && lastIndexNode.tagName != "A") - lastIndexNode = lastIndexNode.nextSibling; - - if(lastIndexNode != null) - { - SelectIndexNode(lastIndexNode); - topicContent.src = lastIndexNode.href; - } - - currentIndexPage = startIndex; - } - } - - xmlHttp.send(null) -} - -// Set the style of the specified keyword index node to "selected" -function SelectIndexNode(node) -{ - if(lastIndexNode != null) - lastIndexNode.className = "UnselectedNode"; - - node.className = "SelectedNode"; - lastIndexNode = node; - - return true; -} - -// Changes the current page with keyword index forward or backward -function ChangeIndexPage(direction) -{ - PopulateIndex(currentIndexPage + direction); - - return false; -} - -// Show a direct link to the currently displayed topic -function ShowDirectLink() -{ - var url = GetCurrentUrl(); - var base = window.location.href; - - if(base.indexOf("?") > 0) - base = base.substr(0, base.indexOf("?") + 1); - - base = base.substr(0, base.lastIndexOf("/") + 1); - - var relative = url.substr(base.length); - - // Using prompt lets the user copy it from the text box - prompt("Direct link", base + "?topic=" + relative); -} +//============================================================================= +// System : Sandcastle Help File Builder +// File : TOC.js +// Author : Eric Woodruff (Eric@EWoodruff.us) +// Updated : 07/25/2012 +// Note : Copyright 2006-2012, Eric Woodruff, All rights reserved +// Compiler: JavaScript +// +// This file contains the methods necessary to implement a simple tree view +// for the table of content with a resizable splitter and Ajax support to +// load tree nodes on demand. It also contains the script necessary to do +// full-text searches. +// +// This code is published under the Microsoft Public License (Ms-PL). A copy +// of the license should be distributed with the code. It can also be found +// at the project website: http://SHFB.CodePlex.com. This notice, the +// author's name, and all copyright notices must remain intact in all +// applications, documentation, and source files. +// +// Version Date Who Comments +// ============================================================================ +// 1.3.0.0 09/12/2006 EFW Created the code +// 1.4.0.2 06/15/2007 EFW Reworked to get rid of frame set and to add +// support for Ajax to load tree nodes on demand. +// 1.5.0.0 06/24/2007 EFW Added full-text search capabilities +// 1.6.0.7 04/01/2008 EFW Merged changes from Ferdinand Prantl to add a +// website keyword index. Added support for "topic" +// query string option. +// 1.9.4.0 02/21/2012 EFW Merged code from Thomas Levesque to show direct +// link and support other page types like PHP. +// 1.9.5.0 07/25/2012 EFW Made changes to support IE 10. +//============================================================================= + +// IE and Chrome flags +var isIE = (navigator.userAgent.indexOf("MSIE") >= 0); +var isIE10OrLater = /MSIE 1\d\./.test(navigator.userAgent); +var isChrome = (navigator.userAgent.indexOf("Chrome") >= 0); + +// Page extension +var pageExtension = ".aspx"; + +// Minimum width of the TOC div +var minWidth = 100; + +// Elements and sizing info +var divTOC, divSizer, topicContent, divNavOpts, divSearchOpts, divSearchResults, divIndexOpts, divIndexResults, + divTree, docBody, maxWidth, offset, txtSearchText, chkSortByTitle; + +// Last node selected +var lastNode, lastSearchNode, lastIndexNode; + +// Last page with keyword index +var currentIndexPage = 0; + +//============================================================================ + +// Initialize the tree view and resize the content. Pass it the page extension to use (i.e. ".aspx") +// for loading TOC element, index keywords, searching, etc. +function Initialize(extension) +{ + docBody = document.getElementsByTagName("body")[0]; + divTOC = document.getElementById("TOCDiv"); + divSizer = document.getElementById("TOCSizer"); + topicContent = document.getElementById("TopicContent"); + divNavOpts = document.getElementById("divNavOpts"); + divSearchOpts = document.getElementById("divSearchOpts"); + divSearchResults = document.getElementById("divSearchResults"); + divIndexOpts = document.getElementById("divIndexOpts"); + divIndexResults = document.getElementById("divIndexResults"); + divTree = document.getElementById("divTree"); + txtSearchText = document.getElementById("txtSearchText"); + chkSortByTitle = document.getElementById("chkSortByTitle"); + + // Set the page extension if specified + if(typeof(extension) != "undefined" && extension != "") + pageExtension = extension; + + // The sizes are bit off in FireFox + if(!isIE) + divNavOpts.style.width = divSearchOpts.style.width = divIndexOpts.style.width = 292; + + ResizeTree(); + SyncTOC(); + + topicContent.onload = SyncTOC; + + // Use an alternate default page if a topic is specified in + // the query string. + var queryString = document.location.search; + + if(queryString != "") + { + var idx, options = queryString.split(/[\?\=\&]/); + + for(idx = 0; idx < options.length; idx++) + if(options[idx] == "topic" && idx + 1 < options.length) + { + topicContent.src = options[idx + 1]; + break; + } + } +} + +//============================================================================ +// Navigation and expand/collaps code + +// Synchronize the table of content with the selected page if possible +function SyncTOC() +{ + var idx, anchor, base, href, url, anchors, treeNode, saveNode; + + base = window.location.href; + base = base.substr(0, base.lastIndexOf("/") + 1); + + if(base.substr(0, 5) == "file:" && base.substr(0, 8) != "file:///") + base = base.replace("file://", "file:///"); + + url = GetCurrentUrl(); + + if(url == "") + return false; + + if(url.substr(0, 5) == "file:" && url.substr(0, 8) != "file:///") + url = url.replace("file://", "file:///"); + + while(true) + { + anchors = divTree.getElementsByTagName("A"); + anchor = null; + + for(idx = 0; idx < anchors.length; idx++) + { + href = anchors[idx].href; + + if(href.substring(0, 7) != 'http://' && href.substring(0, 8) != 'https://' && + href.substring(0, 7) != 'file://') + href = base + href; + + if(href == url) + { + anchor = anchors[idx]; + break; + } + } + + if(anchor == null) + { + // If it contains a "#", strip anything after that and try again + if(url.indexOf("#") != -1) + { + url = url.substr(0, url.indexOf("#")); + continue; + } + + return; + } + + break; + } + + // If found, select it and find the parent tree node + SelectNode(anchor); + saveNode = anchor; + lastNode = null; + + while(anchor != null) + { + if(anchor.className == "TreeNode") + { + treeNode = anchor; + break; + } + + anchor = anchor.parentNode; + } + + // Expand it and all of its parents + while(anchor != null) + { + Expand(anchor); + + anchor = anchor.parentNode; + + while(anchor != null) + { + if(anchor.className == "TreeNode") + break; + + anchor = anchor.parentNode; + } + } + + lastNode = saveNode; + + // Scroll the node into view + var windowTop = lastNode.offsetTop - divTree.offsetTop - divTree.scrollTop; + var windowBottom = divTree.clientHeight - windowTop - lastNode.offsetHeight; + + if(windowTop < 0) + divTree.scrollTop += windowTop - 30; + else + if(windowBottom < 0) + divTree.scrollTop -= windowBottom - 30; +} + +// Get the currently loaded URL from the IFRAME +function GetCurrentUrl() +{ + var base, url = ""; + + try + { + url = window.frames["TopicContent"].document.URL.replace(/\\/g, "/"); + } + catch(e) + { + // If this happens the user probably navigated to another frameset that didn't make itself the topmost + // frameset and we don't have control of the other frame anymore. In that case, just reload our index + // page. + base = window.location.href; + base = base.substr(0, base.lastIndexOf("/") + 1); + + // Chrome is too secure and won't let you access frame URLs when running from the file system unless + // you run Chrome with the "--disable-web-security" command line option. + if(isChrome && base.substr(0, 5) == "file:") + { + alert("Chrome security prevents access to file-based frame URLs. As such, the TOC will not work " + + "with Index.html. Either run this website on a web server, run Chrome with the " + + "'--disable-web-security' command line option, or use FireFox or Internet Explorer."); + + return ""; + } + + if(base.substr(0, 5) == "file:" && base.substr(0, 8) != "file:///") + base = base.replace("file://", "file:///"); + + if(base.substr(0, 5) == "file:") + top.location.href = base + "Index.html"; + else + top.location.href = base + "index" + pageExtension; // Use lowercase on name for case-sensitive servers + } + + return url; +} + +// Expand or collapse all nodes +function ExpandOrCollapseAll(expandNodes) +{ + var divIdx, childIdx, img, divs = document.getElementsByTagName("DIV"); + var childNodes, child, div, link, img; + + for(divIdx = 0; divIdx < divs.length; divIdx++) + if(divs[divIdx].className == "Hidden" || divs[divIdx].className == "Visible") + { + childNodes = divs[divIdx].parentNode.childNodes; + + for(childIdx = 0; childIdx < childNodes.length; childIdx++) + { + child = childNodes[childIdx]; + + if(child.className == "TreeNodeImg") + img = child; + + if(child.className == "Hidden" || child.className == "Visible") + { + div = child; + break; + } + } + + if(div.className == "Visible" && !expandNodes) + { + div.className = "Hidden"; + img.src = "Collapsed.gif"; + } + else + if(div.className == "Hidden" && expandNodes) + { + div.className = "Visible"; + img.src = "Expanded.gif"; + + if(div.innerHTML == "") + FillNode(div, true) + } + } +} + +// Toggle the state of the specified node +function Toggle(node) +{ + var i, childNodes, child, div, link; + + childNodes = node.parentNode.childNodes; + + for(i = 0; i < childNodes.length; i++) + { + child = childNodes[i]; + + if(child.className == "Hidden" || child.className == "Visible") + { + div = child; + break; + } + } + + if(div.className == "Visible") + { + div.className = "Hidden"; + node.src = "Collapsed.gif"; + } + else + { + div.className = "Visible"; + node.src = "Expanded.gif"; + + if(div.innerHTML == "") + FillNode(div, false) + } +} + +// Expand the selected node +function Expand(node) +{ + var i, childNodes, child, div, img; + + // If not valid, don't bother + if(GetCurrentUrl() == "") + return false; + + if(node.tagName == "A") + childNodes = node.parentNode.childNodes; + else + childNodes = node.childNodes; + + for(i = 0; i < childNodes.length; i++) + { + child = childNodes[i]; + + if(child.className == "TreeNodeImg") + img = child; + + if(child.className == "Hidden" || child.className == "Visible") + { + div = child; + break; + } + } + + if(lastNode != null) + lastNode.className = "UnselectedNode"; + + div.className = "Visible"; + img.src = "Expanded.gif"; + + if(node.tagName == "A") + { + node.className = "SelectedNode"; + lastNode = node; + } + + if(div.innerHTML == "") + FillNode(div, false) + + return true; +} + +// Set the style of the specified node to "selected" +function SelectNode(node) +{ + // If not valid, don't bother + if(GetCurrentUrl() == "") + return false; + + if(lastNode != null) + lastNode.className = "UnselectedNode"; + + node.className = "SelectedNode"; + lastNode = node; + + return true; +} + +//============================================================================ +// Ajax-related code used to fill the tree nodes on demand + +function GetXmlHttpRequest() +{ + var xmlHttp = null; + + // If IE7, Mozilla, Safari, etc., use the native object. Otherwise, use the ActiveX control for IE5.x and IE6. + if(window.XMLHttpRequest) + xmlHttp = new XMLHttpRequest(); + else + if(window.ActiveXObject) + xmlHttp = new ActiveXObject("MSXML2.XMLHTTP.3.0"); + + return xmlHttp; +} + +// Perform an AJAX-style request for the contents of a node and put the contents into the empty div +function FillNode(div, expandChildren) +{ + var xmlHttp = GetXmlHttpRequest(), now = new Date(); + + if(xmlHttp == null) + { + div.innerHTML = "XML HTTP request not supported!"; + return; + } + + div.innerHTML = "Loading..."; + + // Add a unique hash to ensure it doesn't use cached results + xmlHttp.open("GET", "FillNode" + pageExtension + "?Id=" + div.id + "&hash=" + now.getTime(), true); + + xmlHttp.onreadystatechange = function() + { + if(xmlHttp.readyState == 4) + { + div.innerHTML = xmlHttp.responseText; + + if(expandChildren) + ExpandOrCollapseAll(true); + } + } + + xmlHttp.send(null) +} + +//============================================================================ +// Resizing code + +// Resize the tree div so that it fills the document body +function ResizeTree() +{ + var y, newHeight; + + if(self.innerHeight) // All but IE + y = self.innerHeight; + else // IE - Strict + if(document.documentElement && document.documentElement.clientHeight) + y = document.documentElement.clientHeight; + else // Everything else + if(document.body) + y = document.body.clientHeight; + + newHeight = y - parseInt(divNavOpts.style.height, 10) - 6; + + if(newHeight < 50) + newHeight = 50; + + divTree.style.height = newHeight; + + newHeight = y - parseInt(divSearchOpts.style.height, 10) - 6; + + if(newHeight < 100) + newHeight = 100; + + divSearchResults.style.height = newHeight; + + newHeight = y - parseInt(divIndexOpts.style.height, 10) - 6; + + if(newHeight < 25) + newHeight = 25; + + divIndexResults.style.height = newHeight; + + // Resize the content div + ResizeContent(); +} + +// Resize the content div +function ResizeContent() +{ + // IE 10 sizes the frame like FireFox and Chrome + if(isIE && !isIE10OrLater) + maxWidth = docBody.clientWidth - 1; + else + maxWidth = docBody.clientWidth - 4; + + topicContent.style.width = maxWidth - (divSizer.offsetLeft + divSizer.offsetWidth); + maxWidth -= minWidth; +} + +// This is called to prepare for dragging the sizer div +function OnMouseDown(event) +{ + var x; + + // Make sure the splitter is at the top of the z-index + divSizer.style.zIndex = 5000; + + // The content is in an IFRAME which steals mouse events so hide it while resizing + topicContent.style.display = "none"; + + if(isIE) + x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft; + else + x = event.clientX + window.scrollX; + + // Save starting offset + offset = parseInt(divSizer.style.left, 10); + + if(isNaN(offset)) + offset = 0; + + offset -= x; + + if(isIE) + { + document.attachEvent("onmousemove", OnMouseMove); + document.attachEvent("onmouseup", OnMouseUp); + window.event.cancelBubble = true; + window.event.returnValue = false; + } + else + { + document.addEventListener("mousemove", OnMouseMove, true); + document.addEventListener("mouseup", OnMouseUp, true); + event.preventDefault(); + } +} + +// Resize the TOC and content divs as the sizer is dragged +function OnMouseMove(event) +{ + var x, pos; + + // Get cursor position with respect to the page + if(isIE) + x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft; + else + x = event.clientX + window.scrollX; + + left = offset + x; + + // Adjusts the width of the TOC divs + pos = (event.clientX > maxWidth) ? maxWidth : (event.clientX < minWidth) ? minWidth : event.clientX; + + divTOC.style.width = divSearchResults.style.width = divIndexResults.style.width = divTree.style.width = pos; + + if(!isIE) + pos -= 8; + + divNavOpts.style.width = divSearchOpts.style.width = divIndexOpts.style.width = pos; + + // Resize the content div to fit in the remaining space + ResizeContent(); +} + +// Finish the drag operation when the mouse button is released +function OnMouseUp(event) +{ + if(isIE) + { + document.detachEvent("onmousemove", OnMouseMove); + document.detachEvent("onmouseup", OnMouseUp); + } + else + { + document.removeEventListener("mousemove", OnMouseMove, true); + document.removeEventListener("mouseup", OnMouseUp, true); + } + + // Show the content div again + topicContent.style.display = "inline"; +} + +//============================================================================ +// Search code + +function ShowHideSearch(show) +{ + if(show) + { + divNavOpts.style.display = divTree.style.display = "none"; + divSearchOpts.style.display = divSearchResults.style.display = ""; + } + else + { + divSearchOpts.style.display = divSearchResults.style.display = "none"; + divNavOpts.style.display = divTree.style.display = ""; + } +} + +// When enter is hit in the search text box, do the search +function OnSearchTextKeyPress(evt) +{ + if(evt.keyCode == 13) + { + PerformSearch(); + return false; + } + + return true; +} + +// Perform a keyword search +function PerformSearch() +{ + var xmlHttp = GetXmlHttpRequest(), now = new Date(); + + if(xmlHttp == null) + { + divSearchResults.innerHTML = "XML HTTP request not supported!"; + return; + } + + divSearchResults.innerHTML = "Searching..."; + + // Add a unique hash to ensure it doesn't use cached results + xmlHttp.open("GET", "SearchHelp" + pageExtension + "?Keywords=" + txtSearchText.value + + "&SortByTitle=" + (chkSortByTitle.checked ? "true" : "false") + + "&hash=" + now.getTime(), true); + + xmlHttp.onreadystatechange = function() + { + if(xmlHttp.readyState == 4) + { + divSearchResults.innerHTML = xmlHttp.responseText; + + lastSearchNode = divSearchResults.childNodes[0].childNodes[1]; + + while(lastSearchNode != null && lastSearchNode.tagName != "A") + lastSearchNode = lastSearchNode.nextSibling; + + if(lastSearchNode != null) + { + SelectSearchNode(lastSearchNode); + topicContent.src = lastSearchNode.href; + } + } + } + + xmlHttp.send(null) +} + +// Set the style of the specified search result node to "selected" +function SelectSearchNode(node) +{ + if(lastSearchNode != null) + lastSearchNode.className = "UnselectedNode"; + + node.className = "SelectedNode"; + lastSearchNode = node; + + return true; +} + +//============================================================================ +// KeyWordIndex code + +function ShowHideIndex(show) +{ + if(show) + { + PopulateIndex(currentIndexPage); + + divNavOpts.style.display = divTree.style.display = "none"; + divIndexOpts.style.display = divIndexResults.style.display = ""; + } + else + { + divIndexOpts.style.display = divIndexResults.style.display = "none"; + divNavOpts.style.display = divTree.style.display = ""; + } +} + +// Populate keyword index +function PopulateIndex(startIndex) +{ + var xmlHttp = GetXmlHttpRequest(), now = new Date(); + var firstNode; + + if(xmlHttp == null) + { + divIndexResults.innerHTML = "XML HTTP request not supported!"; + return; + } + + divIndexResults.innerHTML = "Loading keyword index..."; + + // Add a unique hash to ensure it doesn't use cached results + xmlHttp.open("GET", "LoadIndexKeywords" + pageExtension + "?StartIndex=" + startIndex + + "&hash=" + now.getTime(), true); + + xmlHttp.onreadystatechange = function() + { + if(xmlHttp.readyState == 4) + { + divIndexResults.innerHTML = xmlHttp.responseText; + + if(startIndex > 0) + { + firstNode = divIndexResults.childNodes[1]; + + if(firstNode != null && !firstNode.innerHTML) + firstNode = divIndexResults.childNodes[2]; + } + else + firstNode = divIndexResults.childNodes[0]; + + if(firstNode != null) + lastIndexNode = firstNode.childNodes[0]; + + while(lastIndexNode != null && lastIndexNode.tagName != "A") + lastIndexNode = lastIndexNode.nextSibling; + + if(lastIndexNode != null) + { + SelectIndexNode(lastIndexNode); + topicContent.src = lastIndexNode.href; + } + + currentIndexPage = startIndex; + } + } + + xmlHttp.send(null) +} + +// Set the style of the specified keyword index node to "selected" +function SelectIndexNode(node) +{ + if(lastIndexNode != null) + lastIndexNode.className = "UnselectedNode"; + + node.className = "SelectedNode"; + lastIndexNode = node; + + return true; +} + +// Changes the current page with keyword index forward or backward +function ChangeIndexPage(direction) +{ + PopulateIndex(currentIndexPage + direction); + + return false; +} + +// Show a direct link to the currently displayed topic +function ShowDirectLink() +{ + var url = GetCurrentUrl(); + var base = window.location.href; + + if(base.indexOf("?") > 0) + base = base.substr(0, base.indexOf("?") + 1); + + base = base.substr(0, base.lastIndexOf("/") + 1); + + var relative = url.substr(base.length); + + // Using prompt lets the user copy it from the text box + prompt("Direct link", base + "?topic=" + relative); +} diff --git a/docs/api/html/M_MoreLinq_MoreEnumerable_Acquire__1.htm b/docs/api/html/M_MoreLinq_MoreEnumerable_Acquire__1.htm index 982d69aae..c17c94579 100644 --- a/docs/api/html/M_MoreLinq_MoreEnumerable_Acquire__1.htm +++ b/docs/api/html/M_MoreLinq_MoreEnumerable_Acquire__1.htm @@ -1,33 +1,33 @@ -Acquire Method (source)
MoreLinq
Acquire<(Of <(<'TSource>)>)> Method (source)
NamespacesMoreLinqMoreEnumerableAcquire<(Of <<'(TSource>)>>)(IEnumerable<(Of <<'(TSource>)>>))
- Ensures that a source sequence of IDisposable - objects are all acquired successfully. If the acquisition of any - one IDisposable fails then those successfully - acquired till that point are disposed. -
Declaration Syntax
C#Visual BasicVisual C++
-public static TSource[] Acquire<TSource>(
-	this IEnumerable<TSource> source
-)
-where TSource : IDisposable
-
-<ExtensionAttribute> _
-Public Shared Function Acquire(Of TSource As IDisposable) ( _
-	source As IEnumerable(Of TSource) _
-) As TSource()
-public:
-[ExtensionAttribute]
-generic<typename TSource>
-where TSource : IDisposable
-static array<TSource>^ Acquire(
-	IEnumerable<TSource>^ source
-)
Generic Template Parameters
TSource
Type of elements in source sequence.
Parameters
source (IEnumerable<(Of <(<'TSource>)>)>)
Source sequence of IDisposable objects.
Return Value
- Returns an array of all the acquired IDisposable - object and in source order. -
Usage Note
In Visual Basic and C#, you can call this method as an instance method on any object of type IEnumerable<(Of <(<'TSource>)>)>. When you use instance method syntax to call this method, omit the first parameter.
Remarks
- This operator executes immediately. -