From ba6ec3202eba1da2ff4e95dab847a7541ccdb155 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Sat, 25 Jun 2011 04:10:33 +0000 Subject: [PATCH] -Changed Newtonsoft.Json.Net20.dll to use LinqBridge source code rather than ilmerge to fix error --- Build/build.ps1 | 14 +- Src/Lib/LinqBridge.dll | Bin 64512 -> 0 bytes Src/Newtonsoft.Json.Net20.sln | 1 - Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs | 9 + .../Newtonsoft.Json.Tests.Net20.csproj | 4 - Src/Newtonsoft.Json.Tests/PerformanceTests.cs | 70 +- .../Properties/AssemblyInfo.cs | 2 +- .../DynamicReflectionDelegateFactoryTests.cs | 38 + Src/Newtonsoft.Json/Linq/Extensions.cs | 19 +- Src/Newtonsoft.Json/Linq/JObject.cs | 8 +- .../Newtonsoft.Json.Net20.csproj | 5 +- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonTypeReflector.cs | 1 + .../DynamicReflectionDelegateFactory.cs | 77 +- Src/Newtonsoft.Json/Utilities/LinqBridge.cs | 3108 +++++++++++++++++ 15 files changed, 3291 insertions(+), 67 deletions(-) delete mode 100644 Src/Lib/LinqBridge.dll create mode 100644 Src/Newtonsoft.Json/Utilities/LinqBridge.cs diff --git a/Build/build.ps1 b/Build/build.ps1 index 934e47b0..3282bc18 100644 --- a/Build/build.ps1 +++ b/Build/build.ps1 @@ -58,20 +58,8 @@ task Build -depends Clean { } } -# Merge LinqBridge into .NET 2.0 build -task Merge -depends Build { - $binaryDir = "$sourceDir\Newtonsoft.Json\bin\Release\Net20" - MergeAssembly "$binaryDir\Newtonsoft.Json.Net20.dll" $signKeyPath "$binaryDir\LinqBridge.dll" - del $binaryDir\LinqBridge.dll - - $binaryDir = "$sourceDir\Newtonsoft.Json.Tests\bin\Release\Net20" - MergeAssembly "$binaryDir\Newtonsoft.Json.Tests.Net20.dll" $signKeyPath "$binaryDir\LinqBridge.dll" - MergeAssembly "$binaryDir\Newtonsoft.Json.Net20.dll" $signKeyPath "$binaryDir\LinqBridge.dll" - del $binaryDir\LinqBridge.dll -} - # Optional build documentation, add files to final zip -task Package -depends Merge { +task Package -depends Build { foreach ($build in $builds) { $name = $build.TestsName diff --git a/Src/Lib/LinqBridge.dll b/Src/Lib/LinqBridge.dll deleted file mode 100644 index 305c9bb4cee7b686694742fa9b505b3011317d5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64512 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 diff --git a/Src/Newtonsoft.Json.Net20.sln b/Src/Newtonsoft.Json.Net20.sln index e47a28c2..3634b651 100644 --- a/Src/Newtonsoft.Json.Net20.sln +++ b/Src/Newtonsoft.Json.Net20.sln @@ -3,7 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{620042D9-2753-48F5-BEDE-3905248781D2}" ProjectSection(SolutionItems) = preProject - Lib\LinqBridge.dll = Lib\LinqBridge.dll Lib\NUnit\DotNet\nunit.framework.dll = Lib\NUnit\DotNet\nunit.framework.dll Lib\NUnit\DotNet\nunit.framework.xml = Lib\NUnit\DotNet\nunit.framework.xml EndProjectSection diff --git a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs index 253b3418..16ebf467 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JValueTests.cs @@ -223,6 +223,15 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual(1, c); } + [Test] + public void ConvertValueToFormattableType() + { + IFormattable f = (new JValue(1).Value()); + Assert.AreEqual(1, f); + + Assert.AreEqual("01", f.ToString("00", CultureInfo.InvariantCulture)); + } + [Test] public void Ordering() { diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj index fd80fef5..33061ae3 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj @@ -63,10 +63,6 @@ AllRules.ruleset - - False - ..\Lib\LinqBridge.dll - False ..\Lib\NUnit\DotNet\nunit.framework.dll diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index 54a7ba96..23536a5d 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.IO; using System.Runtime.Serialization; using System.Web.Script.Serialization; +using System.Xml.Linq; using System.Xml.Serialization; using Newtonsoft.Json.Utilities; using NUnit.Framework; @@ -146,6 +147,71 @@ namespace Newtonsoft.Json.Tests }, "JObject"); } + [Test] + public void BuildJObjectComparedToXml() + { + const long totalIterations = 100000; + + const String xml = + @" + + 1 + 2 + 3 + 4 + 5 + "; + + const String json = + @"{ + ""Property1"":""1"", + ""Property2"":""2"", + ""Property3"":""3"", + ""Property4"":""4"", + ""Property5"":""5"" + }"; + + + var watch = new Stopwatch(); + watch.Start(); + for (long iteration = 0; iteration < totalIterations; ++iteration) + { + var obj = JObject.Parse(json); + obj["Property1"].Value(); + obj["Property2"].Value(); + obj["Property3"].Value(); + obj["Property4"].Value(); + obj["Property5"].Value(); + } + watch.Stop(); + var performance1 = (totalIterations / watch.ElapsedMilliseconds) * 1000; + Console.WriteLine("JSON: " + watch.Elapsed.TotalSeconds); + + watch.Reset(); + watch.Start(); + for (long iteration = 0; iteration < totalIterations; ++iteration) + { + var doc = XDocument.Parse(xml); + var alarmProperties = doc.Descendants("property"); + foreach (var property in alarmProperties) + { + var attr = property.Attribute("name"); + var name = attr.Value; + switch (name) + { + case "Property1": Int32.Parse(property.Value); break; + case "Property2": Int32.Parse(property.Value); break; + case "Property3": Int32.Parse(property.Value); break; + case "Property4": Int32.Parse(property.Value); break; + case "Property5": Int32.Parse(property.Value); break; + } + } + } + watch.Stop(); + var performance2 = (totalIterations / watch.ElapsedMilliseconds) * 1000; + Console.WriteLine("XML: " + watch.Elapsed.TotalSeconds); + } + private void SerializeSize(object value) { // this is extremely slow with 5000 interations @@ -547,7 +613,7 @@ namespace Newtonsoft.Json.Tests { JObject test = JObject.Parse(JsonText); IsoDateTimeConverter isoDateTimeConverter = null;// = new IsoDateTimeConverter(); - MemoryStream ms = new MemoryStream(); + MemoryStream ms = new MemoryStream(); TimeOperation(() => { @@ -559,7 +625,7 @@ namespace Newtonsoft.Json.Tests test.WriteTo(jsonTextWriter); jsonTextWriter.Flush(); ms.ToArray(); - + //Encoding.UTF8.GetBytes(test.ToString(Formatting.None)); } return null; diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 96fae985..95dd4f83 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -41,5 +41,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.2.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.2.13801")] +[assembly: AssemblyFileVersion("4.0.2.13825")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs index c8123fe9..59c39b00 100644 --- a/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs +++ b/Src/Newtonsoft.Json.Tests/Utilities/DynamicReflectionDelegateFactoryTests.cs @@ -28,7 +28,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Reflection.Emit; using System.Text; +using Newtonsoft.Json.Tests.Linq; using NUnit.Framework; using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Tests.TestObjects; @@ -107,6 +109,42 @@ namespace Newtonsoft.Json.Tests.Utilities JsonSerializerTest.DictionaryKey key = (JsonSerializerTest.DictionaryKey) result; Assert.AreEqual("First!", key.Value); } + + //[Test] + //public void sdfsdf() + //{ + // string name = "MyAssembly"; + // string filename = name + ".dll"; + + // AssemblyName s = new AssemblyName(name); + + // AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(s, AssemblyBuilderAccess.RunAndSave); + // ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(filename, filename); + // TypeBuilder typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Class, typeof(object)); + // MethodBuilder methodBuilder = typeBuilder.DefineMethod("TestSet", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { typeof(object), typeof(object) }); + + // DynamicReflectionDelegateFactory.GenerateCreateSetFieldIL(typeof(ClassWithGuid).GetField("GuidField"), methodBuilder.GetILGenerator()); + // typeBuilder.CreateType(); + // assemblyBuilder.Save(filename); + //} + + //[Test] + //public void sdfsdf1() + //{ + // string name = "MyAssembly1"; + // string filename = name + ".dll"; + + // AssemblyName s = new AssemblyName(name); + + // AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(s, AssemblyBuilderAccess.RunAndSave); + // ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(filename, filename); + // TypeBuilder typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Class, typeof(object)); + // MethodBuilder methodBuilder = typeBuilder.DefineMethod("TestSet", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { typeof(object), typeof(object) }); + + // DynamicReflectionDelegateFactory.GenerateCreateSetPropertyIL(typeof(Car).GetProperty("Model"), methodBuilder.GetILGenerator()); + // typeBuilder.CreateType(); + // assemblyBuilder.Save(filename); + //} } } #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/Extensions.cs b/Src/Newtonsoft.Json/Linq/Extensions.cs index 716c5c3c..d4b52726 100644 --- a/Src/Newtonsoft.Json/Linq/Extensions.cs +++ b/Src/Newtonsoft.Json/Linq/Extensions.cs @@ -236,33 +236,26 @@ namespace Newtonsoft.Json.Linq { ValidationUtils.ArgumentNotNull(source, "source"); - bool cast = typeof(JToken).IsAssignableFrom(typeof(U)); - foreach (JToken token in source) { - yield return Convert(token, cast); + yield return Convert(token); } } internal static U Convert(this T token) where T : JToken { - bool cast = typeof(JToken).IsAssignableFrom(typeof(U)); + if (token == null) + return default(U); - return Convert(token, cast); - } - - internal static U Convert(this T token, bool cast) where T : JToken - { - if (cast) + if (token is U + // don't want to cast JValue to its interfaces, want to get the internal value + && typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable)) { // HACK return (U)(object)token; } else { - if (token == null) - return default(U); - JValue value = token as JValue; if (value == null) throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T))); diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index fd81bc99..121d36f1 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -306,9 +306,11 @@ namespace Newtonsoft.Json.Linq } if (reader.TokenType != JsonToken.StartObject) - throw new Exception( - "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith( - CultureInfo.InvariantCulture, reader.TokenType)); + { + throw new Exception( + "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith( + CultureInfo.InvariantCulture, reader.TokenType)); + } JObject o = new JObject(); o.SetLineInfo(reader as IJsonLineInfo); diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index b9963627..71c9985b 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -68,10 +68,6 @@ AllRules.ruleset - - False - ..\Lib\LinqBridge.dll - @@ -96,6 +92,7 @@ + diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 4a96e921..ad76c2d5 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -110,7 +110,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.0.2.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.0.2.13801")] +[assembly: AssemblyFileVersion("4.0.2.13825")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 1068e135..0a6b31f2 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -338,6 +338,7 @@ namespace Newtonsoft.Json.Serialization { new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess).Demand(); + new SecurityPermission(SecurityPermissionFlag.SkipVerification).Demand(); new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); new SecurityPermission(PermissionState.Unrestricted).Demand(); _dynamicCodeGeneration = true; diff --git a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs index eab9db7b..eaf7d3c6 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs @@ -52,6 +52,13 @@ namespace Newtonsoft.Json.Utilities DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); + GenerateCreateMethodCallIL(method, generator); + + return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); + } + + private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator) + { ParameterInfo[] args = method.GetParameters(); Label argsOk = generator.DefineLabel(); @@ -84,8 +91,8 @@ namespace Newtonsoft.Json.Utilities generator.CallMethod((MethodInfo)method); Type returnType = method.IsConstructor - ? method.DeclaringType - : ((MethodInfo)method).ReturnType; + ? method.DeclaringType + : ((MethodInfo)method).ReturnType; if (returnType != typeof(void)) generator.BoxIfNeeded(returnType); @@ -93,16 +100,21 @@ namespace Newtonsoft.Json.Utilities generator.Emit(OpCodes.Ldnull); generator.Return(); - - return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); } public override Func CreateDefaultConstructor(Type type) { - DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(object), Type.EmptyTypes, type); + DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), Type.EmptyTypes, type); dynamicMethod.InitLocals = true; ILGenerator generator = dynamicMethod.GetILGenerator(); + GenerateCreateDefaultConstructorIL(type, generator); + + return (Func)dynamicMethod.CreateDelegate(typeof(Func)); + } + + private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator) + { if (type.IsValueType) { generator.DeclareLocal(type); @@ -122,20 +134,23 @@ namespace Newtonsoft.Json.Utilities } generator.Return(); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } public override Func CreateGet(PropertyInfo propertyInfo) + { + DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType); + ILGenerator generator = dynamicMethod.GetILGenerator(); + + GenerateCreateGetPropertyIL(propertyInfo, generator); + + return (Func)dynamicMethod.CreateDelegate(typeof(Func)); + } + + private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { MethodInfo getMethod = propertyInfo.GetGetMethod(true); if (getMethod == null) - throw new Exception("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, - propertyInfo.Name)); - - DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType); - - ILGenerator generator = dynamicMethod.GetILGenerator(); + throw new Exception("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name)); if (!getMethod.IsStatic) generator.PushInstance(propertyInfo.DeclaringType); @@ -143,31 +158,40 @@ namespace Newtonsoft.Json.Utilities generator.CallMethod(getMethod); generator.BoxIfNeeded(propertyInfo.PropertyType); generator.Return(); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } public override Func CreateGet(FieldInfo fieldInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType); - ILGenerator generator = dynamicMethod.GetILGenerator(); + GenerateCreateGetFieldIL(fieldInfo, generator); + + return (Func)dynamicMethod.CreateDelegate(typeof(Func)); + } + + private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator) + { if (!fieldInfo.IsStatic) generator.PushInstance(fieldInfo.DeclaringType); generator.Emit(OpCodes.Ldfld, fieldInfo); generator.BoxIfNeeded(fieldInfo.FieldType); generator.Return(); - - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } public override Action CreateSet(FieldInfo fieldInfo) { - DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(object), typeof(object) }, fieldInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); + GenerateCreateSetFieldIL(fieldInfo, generator); + + return (Action)dynamicMethod.CreateDelegate(typeof(Action)); + } + + internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator) + { if (!fieldInfo.IsStatic) generator.PushInstance(fieldInfo.DeclaringType); @@ -175,16 +199,21 @@ namespace Newtonsoft.Json.Utilities generator.UnboxIfNeeded(fieldInfo.FieldType); generator.Emit(OpCodes.Stfld, fieldInfo); generator.Return(); - - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } public override Action CreateSet(PropertyInfo propertyInfo) { - MethodInfo setMethod = propertyInfo.GetSetMethod(true); - DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(object), typeof(object) }, propertyInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); + GenerateCreateSetPropertyIL(propertyInfo, generator); + + return (Action)dynamicMethod.CreateDelegate(typeof(Action)); + } + + internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) + { + MethodInfo setMethod = propertyInfo.GetSetMethod(true); if (!setMethod.IsStatic) generator.PushInstance(propertyInfo.DeclaringType); @@ -192,8 +221,6 @@ namespace Newtonsoft.Json.Utilities generator.UnboxIfNeeded(propertyInfo.PropertyType); generator.CallMethod(setMethod); generator.Return(); - - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } } } diff --git a/Src/Newtonsoft.Json/Utilities/LinqBridge.cs b/Src/Newtonsoft.Json/Utilities/LinqBridge.cs new file mode 100644 index 00000000..21a3400c --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/LinqBridge.cs @@ -0,0 +1,3108 @@ +#if NET20 + +#define LINQBRIDGE_LIB + +#region License, Terms and Author(s) +// +// LINQBridge +// Copyright (c) 2007-9 Atif Aziz, Joseph Albahari. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +// $Id: Enumerable.cs 240 2010-10-19 21:49:03Z azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using LinqBridge; + + #endregion + + /// + /// Provides a set of static (Shared in Visual Basic) methods for + /// querying objects that implement . + /// + + static partial class Enumerable + { + /// + /// Returns the input typed as . + /// + + public static IEnumerable AsEnumerable(IEnumerable source) + { + return source; + } + + /// + /// Returns an empty that has the + /// specified type argument. + /// + + public static IEnumerable Empty() + { + return Sequence.Empty; + } + + /// + /// Converts the elements of an to the + /// specified type. + /// + + public static IEnumerable Cast( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return CastYield(source); + } + + private static IEnumerable CastYield( + IEnumerable source) + { + foreach (var item in source) + yield return (TResult) item; + } + + /// + /// Filters the elements of an based on a specified type. + /// + + public static IEnumerable OfType( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return OfTypeYield(source); + } + + private static IEnumerable OfTypeYield( + IEnumerable source) + { + foreach (var item in source) + if (item is TResult) + yield return (TResult) item; + } + + /// + /// Generates a sequence of integral numbers within a specified range. + /// + /// The value of the first integer in the sequence. + /// The number of sequential integers to generate. + + public static IEnumerable Range(int start, int count) + { + if (count < 0) + throw new ArgumentOutOfRangeException("count", count, null); + + var end = (long) start + count; + if (end - 1 >= int.MaxValue) + throw new ArgumentOutOfRangeException("count", count, null); + + return RangeYield(start, end); + } + + private static IEnumerable RangeYield(int start, long end) + { + for (var i = start; i < end; i++) + yield return i; + } + + /// + /// Generates a sequence that contains one repeated value. + /// + + public static IEnumerable Repeat(TResult element, int count) + { + if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); + + return RepeatYield(element, count); + } + + private static IEnumerable RepeatYield(TResult element, int count) + { + for (var i = 0; i < count; i++) + yield return element; + } + + /// + /// Filters a sequence of values based on a predicate. + /// + + public static IEnumerable Where( + this IEnumerable source, + Func predicate) + { + CheckNotNull(predicate, "predicate"); + + return source.Where((item, i) => predicate(item)); + } + + /// + /// Filters a sequence of values based on a predicate. + /// Each element's index is used in the logic of the predicate function. + /// + + public static IEnumerable Where( + this IEnumerable source, + Func predicate) + { + CheckNotNull(source, "source"); + CheckNotNull(predicate, "predicate"); + + return WhereYield(source, predicate); + } + + private static IEnumerable WhereYield( + IEnumerable source, + Func predicate) + { + var i = 0; + foreach (var item in source) + if (predicate(item, i++)) + yield return item; + } + + /// + /// Projects each element of a sequence into a new form. + /// + + public static IEnumerable Select( + this IEnumerable source, + Func selector) + { + CheckNotNull(selector, "selector"); + + return source.Select((item, i) => selector(item)); + } + + /// + /// Projects each element of a sequence into a new form by + /// incorporating the element's index. + /// + + public static IEnumerable Select( + this IEnumerable source, + Func selector) + { + CheckNotNull(source, "source"); + CheckNotNull(selector, "selector"); + + return SelectYield(source, selector); + } + + private static IEnumerable SelectYield( + IEnumerable source, + Func selector) + { + var i = 0; + foreach (var item in source) + yield return selector(item, i++); + } + + /// + /// Projects each element of a sequence to an + /// and flattens the resulting sequences into one sequence. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> selector) + { + CheckNotNull(selector, "selector"); + + return source.SelectMany((item, i) => selector(item)); + } + + /// + /// Projects each element of a sequence to an , + /// and flattens the resulting sequences into one sequence. The + /// index of each source element is used in the projected form of + /// that element. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> selector) + { + CheckNotNull(selector, "selector"); + + return source.SelectMany(selector, (item, subitem) => subitem); + } + + /// + /// Projects each element of a sequence to an , + /// flattens the resulting sequences into one sequence, and invokes + /// a result selector function on each element therein. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + CheckNotNull(collectionSelector, "collectionSelector"); + + return source.SelectMany((item, i) => collectionSelector(item), resultSelector); + } + + /// + /// Projects each element of a sequence to an , + /// flattens the resulting sequences into one sequence, and invokes + /// a result selector function on each element therein. The index of + /// each source element is used in the intermediate projected form + /// of that element. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + CheckNotNull(source, "source"); + CheckNotNull(collectionSelector, "collectionSelector"); + CheckNotNull(resultSelector, "resultSelector"); + + return SelectManyYield(source, collectionSelector, resultSelector); + } + + private static IEnumerable SelectManyYield( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + var i = 0; + foreach (var item in source) + foreach (var subitem in collectionSelector(item, i++)) + yield return resultSelector(item, subitem); + } + + /// + /// Returns elements from a sequence as long as a specified condition is true. + /// + + public static IEnumerable TakeWhile( + this IEnumerable source, + Func predicate) + { + CheckNotNull(predicate, "predicate"); + + return source.TakeWhile((item, i) => predicate(item)); + } + + /// + /// Returns elements from a sequence as long as a specified condition is true. + /// The element's index is used in the logic of the predicate function. + /// + + public static IEnumerable TakeWhile( + this IEnumerable source, + Func predicate) + { + CheckNotNull(source, "source"); + CheckNotNull(predicate, "predicate"); + + return TakeWhileYield(source, predicate); + } + + private static IEnumerable TakeWhileYield( + this IEnumerable source, + Func predicate) + { + var i = 0; + foreach (var item in source) + if (predicate(item, i++)) + yield return item; + else + break; + } + + private static class Futures + { + public static readonly Func Default = () => default(T); + public static readonly Func Undefined = () => { throw new InvalidOperationException(); }; + } + + /// + /// Base implementation of First operator. + /// + + private static TSource FirstImpl( + this IEnumerable source, + Func empty) + { + CheckNotNull(source, "source"); + Debug.Assert(empty != null); + + var list = source as IList; // optimized case for lists + if (list != null) + return list.Count > 0 ? list[0] : empty(); + + using (var e = source.GetEnumerator()) // fallback for enumeration + return e.MoveNext() ? e.Current : empty(); + } + + /// + /// Returns the first element of a sequence. + /// + + public static TSource First( + this IEnumerable source) + { + return source.FirstImpl(Futures.Undefined); + } + + /// + /// Returns the first element in a sequence that satisfies a specified condition. + /// + + public static TSource First( + this IEnumerable source, + Func predicate) + { + return First(source.Where(predicate)); + } + + /// + /// Returns the first element of a sequence, or a default value if + /// the sequence contains no elements. + /// + + public static TSource FirstOrDefault( + this IEnumerable source) + { + return source.FirstImpl(Futures.Default); + } + + /// + /// Returns the first element of the sequence that satisfies a + /// condition or a default value if no such element is found. + /// + + public static TSource FirstOrDefault( + this IEnumerable source, + Func predicate) + { + return FirstOrDefault(source.Where(predicate)); + } + + /// + /// Base implementation of Last operator. + /// + + private static TSource LastImpl( + this IEnumerable source, + Func empty) + { + CheckNotNull(source, "source"); + + var list = source as IList; // optimized case for lists + if (list != null) + return list.Count > 0 ? list[list.Count - 1] : empty(); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + return empty(); + + var last = e.Current; + while (e.MoveNext()) + last = e.Current; + + return last; + } + } + + /// + /// Returns the last element of a sequence. + /// + public static TSource Last( + this IEnumerable source) + { + return source.LastImpl(Futures.Undefined); + } + + /// + /// Returns the last element of a sequence that satisfies a + /// specified condition. + /// + + public static TSource Last( + this IEnumerable source, + Func predicate) + { + return Last(source.Where(predicate)); + } + + /// + /// Returns the last element of a sequence, or a default value if + /// the sequence contains no elements. + /// + + public static TSource LastOrDefault( + this IEnumerable source) + { + return source.LastImpl(Futures.Default); + } + + /// + /// Returns the last element of a sequence that satisfies a + /// condition or a default value if no such element is found. + /// + + public static TSource LastOrDefault( + this IEnumerable source, + Func predicate) + { + return LastOrDefault(source.Where(predicate)); + } + + /// + /// Base implementation of Single operator. + /// + + private static TSource SingleImpl( + this IEnumerable source, + Func empty) + { + CheckNotNull(source, "source"); + + using (var e = source.GetEnumerator()) + { + if (e.MoveNext()) + { + var single = e.Current; + if (!e.MoveNext()) + return single; + + throw new InvalidOperationException(); + } + + return empty(); + } + } + + /// + /// Returns the only element of a sequence, and throws an exception + /// if there is not exactly one element in the sequence. + /// + + public static TSource Single( + this IEnumerable source) + { + return source.SingleImpl(Futures.Undefined); + } + + /// + /// Returns the only element of a sequence that satisfies a + /// specified condition, and throws an exception if more than one + /// such element exists. + /// + + public static TSource Single( + this IEnumerable source, + Func predicate) + { + return Single(source.Where(predicate)); + } + + /// + /// Returns the only element of a sequence, or a default value if + /// the sequence is empty; this method throws an exception if there + /// is more than one element in the sequence. + /// + + public static TSource SingleOrDefault( + this IEnumerable source) + { + return source.SingleImpl(Futures.Default); + } + + /// + /// Returns the only element of a sequence that satisfies a + /// specified condition or a default value if no such element + /// exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + + public static TSource SingleOrDefault( + this IEnumerable source, + Func predicate) + { + return SingleOrDefault(source.Where(predicate)); + } + + /// + /// Returns the element at a specified index in a sequence. + /// + + public static TSource ElementAt( + this IEnumerable source, + int index) + { + CheckNotNull(source, "source"); + + if (index < 0) + throw new ArgumentOutOfRangeException("index", index, null); + + var list = source as IList; + if (list != null) + return list[index]; + + try + { + return source.SkipWhile((item, i) => i < index).First(); + } + catch (InvalidOperationException) // if thrown by First + { + throw new ArgumentOutOfRangeException("index", index, null); + } + } + + /// + /// Returns the element at a specified index in a sequence or a + /// default value if the index is out of range. + /// + + public static TSource ElementAtOrDefault( + this IEnumerable source, + int index) + { + CheckNotNull(source, "source"); + + if (index < 0) + return default(TSource); + + var list = source as IList; + if (list != null) + return index < list.Count ? list[index] : default(TSource); + + return source.SkipWhile((item, i) => i < index).FirstOrDefault(); + } + + /// + /// Inverts the order of the elements in a sequence. + /// + + public static IEnumerable Reverse( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return ReverseYield(source); + } + + private static IEnumerable ReverseYield(IEnumerable source) + { + var stack = new Stack(); + foreach (var item in source) + stack.Push(item); + + foreach (var item in stack) + yield return item; + } + + /// + /// Returns a specified number of contiguous elements from the start + /// of a sequence. + /// + + public static IEnumerable Take( + this IEnumerable source, + int count) + { + return source.Where((item, i) => i < count); + } + + /// + /// Bypasses a specified number of elements in a sequence and then + /// returns the remaining elements. + /// + + public static IEnumerable Skip( + this IEnumerable source, + int count) + { + return source.Where((item, i) => i >= count); + } + + /// + /// Bypasses elements in a sequence as long as a specified condition + /// is true and then returns the remaining elements. + /// + + public static IEnumerable SkipWhile( + this IEnumerable source, + Func predicate) + { + CheckNotNull(predicate, "predicate"); + + return source.SkipWhile((item, i) => predicate(item)); + } + + /// + /// Bypasses elements in a sequence as long as a specified condition + /// is true and then returns the remaining elements. The element's + /// index is used in the logic of the predicate function. + /// + + public static IEnumerable SkipWhile( + this IEnumerable source, + Func predicate) + { + CheckNotNull(source, "source"); + CheckNotNull(predicate, "predicate"); + + return SkipWhileYield(source, predicate); + } + + private static IEnumerable SkipWhileYield( + IEnumerable source, + Func predicate) + { + using (var e = source.GetEnumerator()) + { + for (var i = 0; ; i++) + { + if (!e.MoveNext()) + yield break; + + if (!predicate(e.Current, i)) + break; + } + + do { yield return e.Current; } while (e.MoveNext()); + } + } + + /// + /// Returns the number of elements in a sequence. + /// + + public static int Count( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + var collection = source as ICollection; + return collection != null + ? collection.Count + : source.Aggregate(0, (count, item) => checked(count + 1)); + } + + /// + /// Returns a number that represents how many elements in the + /// specified sequence satisfy a condition. + /// + + public static int Count( + this IEnumerable source, + Func predicate) + { + return Count(source.Where(predicate)); + } + + /// + /// Returns an that represents the total number + /// of elements in a sequence. + /// + + public static long LongCount( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + var array = source as Array; + return array != null + ? array.LongLength + : source.Aggregate(0L, (count, item) => count + 1); + } + + /// + /// Returns an that represents how many elements + /// in a sequence satisfy a condition. + /// + + public static long LongCount( + this IEnumerable source, + Func predicate) + { + return LongCount(source.Where(predicate)); + } + + /// + /// Concatenates two sequences. + /// + + public static IEnumerable Concat( + this IEnumerable first, + IEnumerable second) + { + CheckNotNull(first, "first"); + CheckNotNull(second, "second"); + + return ConcatYield(first, second); + } + + private static IEnumerable ConcatYield( + IEnumerable first, + IEnumerable second) + { + foreach (var item in first) + yield return item; + + foreach (var item in second) + yield return item; + } + + /// + /// Creates a from an . + /// + + public static List ToList( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return new List(source); + } + + /// + /// Creates an array from an . + /// + + public static TSource[] ToArray( + this IEnumerable source) + { + return source.ToList().ToArray(); + } + + /// + /// Returns distinct elements from a sequence by using the default + /// equality comparer to compare values. + /// + + public static IEnumerable Distinct( + this IEnumerable source) + { + return Distinct(source, /* comparer */ null); + } + + /// + /// Returns distinct elements from a sequence by using a specified + /// to compare values. + /// + + public static IEnumerable Distinct( + this IEnumerable source, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + + return DistinctYield(source, comparer); + } + + private static IEnumerable DistinctYield( + IEnumerable source, + IEqualityComparer comparer) + { + var set = new Dictionary(comparer); + var gotNull = false; + + foreach (var item in source) + { + if (item == null) + { + if (gotNull) + continue; + gotNull = true; + } + else + { + if (set.ContainsKey(item)) + continue; + set.Add(item, null); + } + + yield return item; + } + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector) + { + return ToLookup(source, keySelector, e => e, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function and a key comparer. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return ToLookup(source, keySelector, e => e, comparer); + } + + /// + /// Creates a from an + /// according to specified key + /// and element selector functions. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return ToLookup(source, keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function, a comparer and an element selector function. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + CheckNotNull(elementSelector, "elementSelector"); + + var lookup = new Lookup(comparer); + + foreach (var item in source) + { + var key = keySelector(item); + + var grouping = (Grouping) lookup.Find(key); + if (grouping == null) + { + grouping = new Grouping(key); + lookup.Add(grouping); + } + + grouping.Add(elementSelector(item)); + } + + return lookup; + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector) + { + return GroupBy(source, keySelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and compares the keys by using a specified + /// comparer. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return GroupBy(source, keySelector, e => e, comparer); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and projects the elements for each group by + /// using a specified function. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return GroupBy(source, keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + CheckNotNull(elementSelector, "elementSelector"); + + return ToLookup(source, keySelector, elementSelector, comparer); + } + + /// + /// Groups the elements of a sequence according to a key selector + /// function. The keys are compared by using a comparer and each + /// group's elements are projected by using a specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func, TResult> resultSelector) + { + return GroupBy(source, keySelector, resultSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. The elements of each group are projected by using a + /// specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + CheckNotNull(resultSelector, "resultSelector"); + + return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g)); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. The keys are compared by using a specified comparer. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + Func, TResult> resultSelector) + { + return GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. Key values are compared by using a specified comparer, + /// and the elements of each group are projected by using a + /// specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + CheckNotNull(elementSelector, "elementSelector"); + CheckNotNull(resultSelector, "resultSelector"); + + return ToLookup(source, keySelector, elementSelector, comparer) + .Select(g => resultSelector(g.Key, g)); + } + + /// + /// Applies an accumulator function over a sequence. + /// + + public static TSource Aggregate( + this IEnumerable source, + Func func) + { + CheckNotNull(source, "source"); + CheckNotNull(func, "func"); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + throw new InvalidOperationException(); + + return e.Renumerable().Skip(1).Aggregate(e.Current, func); + } + } + + /// + /// Applies an accumulator function over a sequence. The specified + /// seed value is used as the initial accumulator value. + /// + + public static TAccumulate Aggregate( + this IEnumerable source, + TAccumulate seed, + Func func) + { + return Aggregate(source, seed, func, r => r); + } + + /// + /// Applies an accumulator function over a sequence. The specified + /// seed value is used as the initial accumulator value, and the + /// specified function is used to select the result value. + /// + + public static TResult Aggregate( + this IEnumerable source, + TAccumulate seed, + Func func, + Func resultSelector) + { + CheckNotNull(source, "source"); + CheckNotNull(func, "func"); + CheckNotNull(resultSelector, "resultSelector"); + + var result = seed; + + foreach (var item in source) + result = func(result, item); + + return resultSelector(result); + } + + /// + /// Produces the set union of two sequences by using the default + /// equality comparer. + /// + + public static IEnumerable Union( + this IEnumerable first, + IEnumerable second) + { + return Union(first, second, /* comparer */ null); + } + + /// + /// Produces the set union of two sequences by using a specified + /// . + /// + + public static IEnumerable Union( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return first.Concat(second).Distinct(comparer); + } + + /// + /// Returns the elements of the specified sequence or the type + /// parameter's default value in a singleton collection if the + /// sequence is empty. + /// + + public static IEnumerable DefaultIfEmpty( + this IEnumerable source) + { + return source.DefaultIfEmpty(default(TSource)); + } + + /// + /// Returns the elements of the specified sequence or the specified + /// value in a singleton collection if the sequence is empty. + /// + + public static IEnumerable DefaultIfEmpty( + this IEnumerable source, + TSource defaultValue) + { + CheckNotNull(source, "source"); + + return DefaultIfEmptyYield(source, defaultValue); + } + + private static IEnumerable DefaultIfEmptyYield( + IEnumerable source, + TSource defaultValue) + { + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + yield return defaultValue; + else + do { yield return e.Current; } while (e.MoveNext()); + } + } + + /// + /// Determines whether all elements of a sequence satisfy a condition. + /// + + public static bool All( + this IEnumerable source, + Func predicate) + { + CheckNotNull(source, "source"); + CheckNotNull(predicate, "predicate"); + + foreach (var item in source) + if (!predicate(item)) + return false; + + return true; + } + + /// + /// Determines whether a sequence contains any elements. + /// + + public static bool Any( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + using (var e = source.GetEnumerator()) + return e.MoveNext(); + } + + /// + /// Determines whether any element of a sequence satisfies a + /// condition. + /// + + public static bool Any( + this IEnumerable source, + Func predicate) + { + return source.Where(predicate).Any(); + } + + /// + /// Determines whether a sequence contains a specified element by + /// using the default equality comparer. + /// + + public static bool Contains( + this IEnumerable source, + TSource value) + { + return source.Contains(value, /* comparer */ null); + } + + /// + /// Determines whether a sequence contains a specified element by + /// using a specified . + /// + + public static bool Contains( + this IEnumerable source, + TSource value, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + + if (comparer == null) + { + var collection = source as ICollection; + if (collection != null) + return collection.Contains(value); + } + + comparer = comparer ?? EqualityComparer.Default; + return source.Any(item => comparer.Equals(item, value)); + } + + /// + /// Determines whether two sequences are equal by comparing the + /// elements by using the default equality comparer for their type. + /// + + public static bool SequenceEqual( + this IEnumerable first, + IEnumerable second) + { + return first.SequenceEqual(second, /* comparer */ null); + } + + /// + /// Determines whether two sequences are equal by comparing their + /// elements by using a specified . + /// + + public static bool SequenceEqual( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + CheckNotNull(first, "frist"); + CheckNotNull(second, "second"); + + comparer = comparer ?? EqualityComparer.Default; + + using (IEnumerator lhs = first.GetEnumerator(), + rhs = second.GetEnumerator()) + { + do + { + if (!lhs.MoveNext()) + return !rhs.MoveNext(); + + if (!rhs.MoveNext()) + return false; + } + while (comparer.Equals(lhs.Current, rhs.Current)); + } + + return false; + } + + /// + /// Base implementation for Min/Max operator. + /// + + private static TSource MinMaxImpl( + this IEnumerable source, + Func lesser) + { + CheckNotNull(source, "source"); + Debug.Assert(lesser != null); + + return source.Aggregate((a, item) => lesser(a, item) ? a : item); + } + + /// + /// Base implementation for Min/Max operator for nullable types. + /// + + private static TSource? MinMaxImpl( + this IEnumerable source, + TSource? seed, Func lesser) where TSource : struct + { + CheckNotNull(source, "source"); + Debug.Assert(lesser != null); + + return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item); + // == MinMaxImpl(Repeat(null, 1).Concat(source), lesser); + } + + /// + /// Returns the minimum value in a generic sequence. + /// + + public static TSource Min( + this IEnumerable source) + { + var comparer = Comparer.Default; + return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0); + } + + /// + /// Invokes a transform function on each element of a generic + /// sequence and returns the minimum resulting value. + /// + + public static TResult Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a generic sequence. + /// + + public static TSource Max( + this IEnumerable source) + { + var comparer = Comparer.Default; + return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0); + } + + /// + /// Invokes a transform function on each element of a generic + /// sequence and returns the maximum resulting value. + /// + + public static TResult Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Makes an enumerator seen as enumerable once more. + /// + /// + /// The supplied enumerator must have been started. The first element + /// returned is the element the enumerator was on when passed in. + /// DO NOT use this method if the caller must be a generator. It is + /// mostly safe among aggregate operations. + /// + + private static IEnumerable Renumerable(this IEnumerator e) + { + Debug.Assert(e != null); + + do { yield return e.Current; } while (e.MoveNext()); + } + + /// + /// Sorts the elements of a sequence in ascending order according to a key. + /// + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func keySelector) + { + return source.OrderBy(keySelector, /* comparer */ null); + } + + /// + /// Sorts the elements of a sequence in ascending order by using a + /// specified comparer. + /// + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func keySelector, + IComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + + return new OrderedEnumerable(source, keySelector, comparer, /* descending */ false); + } + + /// + /// Sorts the elements of a sequence in descending order according to a key. + /// + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func keySelector) + { + return source.OrderByDescending(keySelector, /* comparer */ null); + } + + /// + /// Sorts the elements of a sequence in descending order by using a + /// specified comparer. + /// + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func keySelector, + IComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(source, "keySelector"); + + return new OrderedEnumerable(source, keySelector, comparer, /* descending */ true); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// ascending order according to a key. + /// + + public static IOrderedEnumerable ThenBy( + this IOrderedEnumerable source, + Func keySelector) + { + return source.ThenBy(keySelector, /* comparer */ null); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// ascending order by using a specified comparer. + /// + + public static IOrderedEnumerable ThenBy( + this IOrderedEnumerable source, + Func keySelector, + IComparer comparer) + { + CheckNotNull(source, "source"); + + return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// descending order, according to a key. + /// + + public static IOrderedEnumerable ThenByDescending( + this IOrderedEnumerable source, + Func keySelector) + { + return source.ThenByDescending(keySelector, /* comparer */ null); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// descending order by using a specified comparer. + /// + + public static IOrderedEnumerable ThenByDescending( + this IOrderedEnumerable source, + Func keySelector, + IComparer comparer) + { + CheckNotNull(source, "source"); + + return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true); + } + + /// + /// Base implementation for Intersect and Except operators. + /// + + private static IEnumerable IntersectExceptImpl( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer, + bool flag) + { + CheckNotNull(first, "first"); + CheckNotNull(second, "second"); + + var keys = new List(); + var flags = new Dictionary(comparer); + + foreach (var item in first.Where(k => !flags.ContainsKey(k))) + { + flags.Add(item, !flag); + keys.Add(item); + } + + foreach (var item in second.Where(flags.ContainsKey)) + flags[item] = flag; + + // + // As per docs, "the marked elements are yielded in the order in + // which they were collected. + // + + return keys.Where(item => flags[item]); + } + + /// + /// Produces the set intersection of two sequences by using the + /// default equality comparer to compare values. + /// + + public static IEnumerable Intersect( + this IEnumerable first, + IEnumerable second) + { + return first.Intersect(second, /* comparer */ null); + } + + /// + /// Produces the set intersection of two sequences by using the + /// specified to compare values. + /// + + public static IEnumerable Intersect( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return IntersectExceptImpl(first, second, comparer, /* flag */ true); + } + + /// + /// Produces the set difference of two sequences by using the + /// default equality comparer to compare values. + /// + + public static IEnumerable Except( + this IEnumerable first, + IEnumerable second) + { + return first.Except(second, /* comparer */ null); + } + + /// + /// Produces the set difference of two sequences by using the + /// specified to compare values. + /// + + public static IEnumerable Except( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return IntersectExceptImpl(first, second, comparer, /* flag */ false); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector) + { + return source.ToDictionary(keySelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function and key comparer. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return source.ToDictionary(keySelector, e => e); + } + + /// + /// Creates a from an + /// according to specified key + /// selector and element selector functions. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return source.ToDictionary(keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function, a comparer, and an element selector function. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + CheckNotNull(source, "source"); + CheckNotNull(keySelector, "keySelector"); + CheckNotNull(elementSelector, "elementSelector"); + + var dict = new Dictionary(comparer); + + foreach (var item in source) + { + // + // ToDictionary is meant to throw ArgumentNullException if + // keySelector produces a key that is null and + // Argument exception if keySelector produces duplicate keys + // for two elements. Incidentally, the doucmentation for + // IDictionary.Add says that the Add method + // throws the same exceptions under the same circumstances + // so we don't need to do any additional checking or work + // here and let the Add implementation do all the heavy + // lifting. + // + + dict.Add(keySelector(item), elementSelector(item)); + } + + return dict; + } + + /// + /// Correlates the elements of two sequences based on matching keys. + /// The default equality comparer is used to compare keys. + /// + + public static IEnumerable Join( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func resultSelector) + { + return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); + } + + /// + /// Correlates the elements of two sequences based on matching keys. + /// The default equality comparer is used to compare keys. A + /// specified is used to compare keys. + /// + + public static IEnumerable Join( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func resultSelector, + IEqualityComparer comparer) + { + CheckNotNull(outer, "outer"); + CheckNotNull(inner, "inner"); + CheckNotNull(outerKeySelector, "outerKeySelector"); + CheckNotNull(innerKeySelector, "innerKeySelector"); + CheckNotNull(resultSelector, "resultSelector"); + + var lookup = inner.ToLookup(innerKeySelector, comparer); + + return + from o in outer + from i in lookup[outerKeySelector(o)] + select resultSelector(o, i); + } + + /// + /// Correlates the elements of two sequences based on equality of + /// keys and groups the results. The default equality comparer is + /// used to compare keys. + /// + + public static IEnumerable GroupJoin( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func, TResult> resultSelector) + { + return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); + } + + /// + /// Correlates the elements of two sequences based on equality of + /// keys and groups the results. The default equality comparer is + /// used to compare keys. A specified + /// is used to compare keys. + /// + + public static IEnumerable GroupJoin( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + CheckNotNull(outer, "outer"); + CheckNotNull(inner, "inner"); + CheckNotNull(outerKeySelector, "outerKeySelector"); + CheckNotNull(innerKeySelector, "innerKeySelector"); + CheckNotNull(resultSelector, "resultSelector"); + + var lookup = inner.ToLookup(innerKeySelector, comparer); + return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)])); + } + + [DebuggerStepThrough] + private static void CheckNotNull(T value, string name) where T : class + { + if (value == null) + throw new ArgumentNullException(name); + } + + private static class Sequence + { + public static readonly IEnumerable Empty = new T[0]; + } + + private sealed class Grouping : List, IGrouping + { + internal Grouping(K key) + { + Key = key; + } + + public K Key { get; private set; } + } + } +} + +// $Id: Enumerable.g.cs 215 2009-10-03 13:31:49Z azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections.Generic; + + #endregion + + // This partial implementation was template-generated: + // Sat, 03 Oct 2009 09:42:39 GMT + + partial class Enumerable + { + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static int Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + int sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static int Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (int) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static int? Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + int sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static int? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (int) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static int? Min( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static int? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static int? Max( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static int? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static long Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static long Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (long) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static long? Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static long? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + long sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (long) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static long? Min( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static long? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static long? Max( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static long? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static float Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + float sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static float Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static float Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + float sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (float) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (float) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static float Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static float? Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + float sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static float? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static float? Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + float sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (float) num; + count++; + } + + if (count == 0) + return null; + + return (float?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static float? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static float? Min( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static float? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static float? Max( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static float? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static double Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + double sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static double Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + double sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (double) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static double? Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + double sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static double? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + double sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (double) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static double? Min( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static double? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static double? Max( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static double? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static decimal Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + decimal sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static decimal Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static decimal Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + decimal sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (decimal) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (decimal) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static decimal Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static decimal? Sum( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + decimal sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static decimal? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static decimal? Average( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + decimal sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (decimal) num; + count++; + } + + if (count == 0) + return null; + + return (decimal?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static decimal? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static decimal? Min( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static decimal? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static decimal? Max( + this IEnumerable source) + { + CheckNotNull(source, "source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static decimal? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + } +} + +namespace System.Runtime.CompilerServices +{ + /// + /// This attribute allows us to define extension methods without + /// requiring .NET Framework 3.5. For more information, see the section, + /// Extension Methods in .NET Framework 2.0 Apps, + /// of Basic Instincts: Extension Methods + /// column in MSDN Magazine, + /// issue Nov 2007. + /// + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] + internal sealed class ExtensionAttribute : Attribute { } +} + +// $Id: Func.cs 224 2009-10-04 07:13:08Z azizatif $ + +namespace System +{ +#if LINQBRIDGE_LIB + public delegate TResult Func(); + public delegate TResult Func(T a); + public delegate TResult Func(T1 arg1, T2 arg2); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#else + delegate TResult Func(); + delegate TResult Func(T a); + delegate TResult Func(T1 arg1, T2 arg2); + delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); + delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#endif +} + +// $Id: IGrouping.cs 225 2009-10-04 07:16:14Z azizatif $ + +namespace System.Linq +{ + #region Imports + + using System.Collections.Generic; + + #endregion + + /// + /// Represents a collection of objects that have a common key. + /// + + partial interface IGrouping : IEnumerable + { + /// + /// Gets the key of the . + /// + + TKey Key { get; } + } +} + +// $Id: ILookup.cs 224 2009-10-04 07:13:08Z azizatif $ + +namespace System.Linq +{ + using System.Collections.Generic; + + /// + /// Defines an indexer, size property, and Boolean search method for + /// data structures that map keys to + /// sequences of values. + /// + + partial interface ILookup : IEnumerable> + { + bool Contains(TKey key); + int Count { get; } + IEnumerable this[TKey key] { get; } + } +} + +// $Id: IOrderedEnumerable.cs 224 2009-10-04 07:13:08Z azizatif $ + +namespace System.Linq +{ + using System.Collections.Generic; + + /// + /// Represents a sorted sequence. + /// + + partial interface IOrderedEnumerable : IEnumerable + { + /// + /// Performs a subsequent ordering on the elements of an + /// according to a key. + /// + + IOrderedEnumerable CreateOrderedEnumerable( + Func keySelector, IComparer comparer, bool descending); + } +} + +// $Id: Lookup.cs 224 2009-10-04 07:13:08Z azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using IEnumerable=System.Collections.IEnumerable; + + #endregion + + /// + /// Represents a collection of keys each mapped to one or more values. + /// + + internal sealed class Lookup : ILookup + { + private readonly Dictionary> _map; + + internal Lookup(IEqualityComparer comparer) + { + _map = new Dictionary>(comparer); + } + + internal void Add(IGrouping item) + { + _map.Add(item.Key, item); + } + + internal IEnumerable Find(TKey key) + { + IGrouping grouping; + return _map.TryGetValue(key, out grouping) ? grouping : null; + } + + /// + /// Gets the number of key/value collection pairs in the . + /// + + public int Count + { + get { return _map.Count; } + } + + /// + /// Gets the collection of values indexed by the specified key. + /// + + public IEnumerable this[TKey key] + { + get + { + IGrouping result; + return _map.TryGetValue(key, out result) ? result : Enumerable.Empty(); + } + } + + /// + /// Determines whether a specified key is in the . + /// + + public bool Contains(TKey key) + { + return _map.ContainsKey(key); + } + + /// + /// Applies a transform function to each key and its associated + /// values and returns the results. + /// + + public IEnumerable ApplyResultSelector( + Func, TResult> resultSelector) + { + if (resultSelector == null) + throw new ArgumentNullException("resultSelector"); + + foreach (var pair in _map) + yield return resultSelector(pair.Key, pair.Value); + } + + /// + /// Returns a generic enumerator that iterates through the . + /// + + public IEnumerator> GetEnumerator() + { + return _map.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} + +// $Id: OrderedEnumerable.cs 237 2010-01-31 12:20:24Z azizatif $ + +namespace LinqBridge +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + + #endregion + + internal sealed class OrderedEnumerable : IOrderedEnumerable + { + private readonly IEnumerable _source; + private readonly List> _comparisons; + + public OrderedEnumerable(IEnumerable source, + Func keySelector, IComparer comparer, bool descending) : + this(source, null, keySelector, comparer, descending) {} + + private OrderedEnumerable(IEnumerable source, List> comparisons, + Func keySelector, IComparer comparer, bool descending) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + + _source = source; + + comparer = comparer ?? Comparer.Default; + + if (comparisons == null) + comparisons = new List>(/* capacity */ 4); + + comparisons.Add((x, y) + => (descending ? -1 : 1) * comparer.Compare(keySelector(x), keySelector(y))); + + _comparisons = comparisons; + } + + public IOrderedEnumerable CreateOrderedEnumerable( + Func keySelector, IComparer comparer, bool descending) + { + return new OrderedEnumerable(_source, _comparisons, keySelector, comparer, descending); + } + + public IEnumerator GetEnumerator() + { + // + // We sort using List.Sort, but docs say that it performs an + // unstable sort. LINQ, on the other hand, says OrderBy performs + // a stable sort. So convert the source sequence into a sequence + // of tuples where the second element tags the position of the + // element from the source sequence (First). The position is + // then used as a tie breaker when all keys compare equal, + // thus making the sort stable. + // + + var list = _source.Select(new Func>(TagPosition)).ToList(); + + list.Sort((x, y) => + { + // + // Compare keys from left to right. + // + + var comparisons = _comparisons; + for (var i = 0; i < comparisons.Count; i++) + { + var result = comparisons[i](x.First, y.First); + if (result != 0) + return result; + } + + // + // All keys compared equal so now break the tie by their + // position in the original sequence, making the sort stable. + // + + return x.Second.CompareTo(y.Second); + }); + + return list.Select(new Func, T>(GetFirst)).GetEnumerator(); + + } + + /// + /// See issue #11 + /// for why this method is needed and cannot be expressed as a + /// lambda at the call site. + /// + + private static Tuple TagPosition(T e, int i) + { + return new Tuple(e, i); + } + + /// + /// See issue #11 + /// for why this method is needed and cannot be expressed as a + /// lambda at the call site. + /// + + private static T GetFirst(Tuple pv) + { + return pv.First; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} + +// $Id: Tuple.cs 215 2009-10-03 13:31:49Z azizatif $ + +namespace LinqBridge +{ + #region Imports + + using System; + using System.Collections.Generic; + using System.Text; + + #endregion + + [ Serializable ] + internal struct Tuple : IEquatable> + { + public TFirst First { get; private set; } + public TSecond Second { get; private set; } + + public Tuple(TFirst first, TSecond second) : this() + { + First = first; + Second = second; + } + + public override bool Equals(object obj) + { + return obj != null + && obj is Tuple + && base.Equals((Tuple) obj); + } + + public bool Equals(Tuple other) + { + return EqualityComparer.Default.Equals(other.First, First) + && EqualityComparer.Default.Equals(other.Second, Second); + } + + public override int GetHashCode() + { + var num = 0x7a2f0b42; + num = (-1521134295 * num) + EqualityComparer.Default.GetHashCode(First); + return (-1521134295 * num) + EqualityComparer.Default.GetHashCode(Second); + } + + public override string ToString() + { + return string.Format(@"{{ First = {0}, Second = {1} }}", First, Second); + } + } +} + +// $Id: Action.cs 239 2010-02-05 23:26:23Z azizatif $ + +namespace System +{ +#if LINQBRIDGE_LIB + public delegate void Action(); + public delegate void Action(T1 arg1, T2 arg2); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#else + delegate void Action(); + delegate void Action(T1 arg1, T2 arg2); + delegate void Action(T1 arg1, T2 arg2, T3 arg3); + delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#endif +} + +#endif \ No newline at end of file