dotnet/corefx — pull request #181 by alexandrnikitin (2014-12-03 23:38:34+00:00)
Title: Removes unnecessary object allocations because of delegates

I introduced several singletons to store delegate instances to avoid unnecessary object allocation in generic methods.

#### For example
`ParallelEnumerable.PerformAggregation()` method
__Before:__
```csharp
private static T PerformAggregation(this ParallelQuery source,
Func reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
{
Contract.Assert(source != null);
Contract.Assert(reduce != null);
Contract.Assert(options.IsValidQueryAggregationOption(), "enum is out of range");

AssociativeAggregationOperator op = new AssociativeAggregationOperator(
source, seed, null, seedIsSpecified, reduce, reduce, delegate (T obj) { return obj; }, throwIfEmpty, options);
return op.Aggregate();
}
```
```
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.2
IL_0003: ldnull
IL_0004: ldarg.3
IL_0005: ldarg.1
IL_0006: ldarg.1
IL_0007: ldnull
IL_0008: ldftn !!0 System.Linq.ParallelEnumerable::'b__e'(!!0)
>>> IL_000e: newobj instance void class [System.Runtime]System.Func`2::.ctor(object, native int)
IL_0013: ldarg.s throwIfEmpty
IL_0015: ldarg.s options
IL_0017: newobj instance void class System.Linq.Parallel.AssociativeAggregationOperator`3::.ctor(class [System.Runtime]System.Collections.Generic.IEnumerable`1, !1, class [System.Runtime]System.Func`1, bool, class [System.Runtime]System.Func`3, class [System.Runtime]System.Func`3, class [System.Runtime]System.Func`2, bool, valuetype System.Linq.Parallel.QueryAggregationOptions)
IL_001c: stloc.0
IL_001d: ldloc.0
IL_001e: callvirt instance !2 class System.Linq.Parallel.AssociativeAggregationOperator`3::Aggregate()
IL_0023: stloc.1
IL_0024: br.s IL_0026

IL_0026: ldloc.1
IL_0027: ret
```
__After:__

```csharp
private static T PerformAggregation(this ParallelQuery source,
Func reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
{
Contract.Assert(source != null);
Contract.Assert(reduce != null);
Contract.Assert(options.IsValidQueryAggregationOption(), "enum is out of range");

AssociativeAggregationOperator op = new AssociativeAggregationOperator(
source, seed, null, seedIsSpecified, reduce, reduce, IdentityFunction.Instance, throwIfEmpty, options);
return op.Aggregate();
}
```

```
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.2
IL_0003: ldnull
IL_0004: ldarg.3
IL_0005: ldarg.1
IL_0006: ldarg.1
>>> IL_0007: ldsfld class [System.Runtime]System.Func`2 class System.Linq.IdentityFunction`1::Instance
IL_000c: ldarg.s throwIfEmpty
IL_000e: ldarg.s options
IL_0010: newobj instance void class System.Linq.Parallel.AssociativeAggregationOperator`3::.ctor(class [System.Runtime]System.Collections.Generic.IEnumerable`1, !1, class [System.Runtime]System.Func`1, bool, class [System.Runtime]System.Func`3, class [System.Runtime]System.Func`3, class [System.Runtime]System.Func`2, bool, valuetype System.Linq.Parallel.QueryAggregationOptions)
IL_0015: stloc.0
IL_0016: ldloc.0
IL_0017: callvirt instance !2 class System.Linq.Parallel.AssociativeAggregationOperator`3::Aggregate()
IL_001c: stloc.1
IL_001d: br.s IL_001f

IL_001f: ldloc.1
IL_0020: ret

```

Where `IdentityFunction` looks like
```csharp
internal class IdentityFunction
{
public static readonly Func Instance = Function;

private static T Function(T arg)
{
return arg;
}
}
```