using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading.Tasks;
public static class External
static List<int> list = new List<int>();
static public void Func(Action<List<int>> act)
foreach (var x in Enumerable.Range(0, 1000))
Enumerable.Range(x, 1000).ToList().ForEach(a => list.Add(a));
Enumerable.Range(x, 1000).ToList().ForEach(a => list.Add(-a));
static void Main(string[] args)
Stopwatch t = new Stopwatch();
Console.WriteLine("Wrapper1:");
total = new Wrapper1<List<int>>(External.Func).SelectMany(x => x).Sum();
Console.WriteLine("Total: {0}, time: {1}", total, t.ElapsedMilliseconds);
Console.WriteLine("Wrapper2:");
total = new Wrapper2<List<int>>(External.Func).SelectMany(x => x).Sum();
Console.WriteLine("Total: {0}, time: {1}", total, t.ElapsedMilliseconds);
public class Wrapper1<T> : IEnumerable<T>
List<T> list = new List<T>();
public Wrapper1(Action<Action<T>> act) => act(x => list.Add(Clone(x)));
public IEnumerator<T> GetEnumerator() => list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
public static T Clone(T source)
if (!typeof(T).IsSerializable) throw new ArgumentException("The type must be serializable.", "source");
if (Object.ReferenceEquals(source, null)) return default(T);
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
class Wrapper2<T> : IEnumerable<T>
private readonly Action<Action<T>> _external;
public Wrapper2(Action<Action<T>> externalFunc)
_external = externalFunc;
public IEnumerator<T> GetEnumerator()
return new List<T>().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()